superacli 1.1.5 → 1.1.7

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 (1081) hide show
  1. package/README.md +77 -53
  2. package/__tests__/azd-plugin.test.js +109 -0
  3. package/__tests__/config.test.js +4 -3
  4. package/__tests__/discover.test.js +59 -0
  5. package/__tests__/goose-plugin.test.js +149 -0
  6. package/__tests__/help-json.test.js +2 -0
  7. package/__tests__/openhands-plugin.test.js +106 -0
  8. package/__tests__/plugin-cocoindex-code-uninstall.test.js +19 -0
  9. package/__tests__/plugin-cocoindex-code.test.js +37 -0
  10. package/__tests__/plugin-install-guidance.test.js +81 -0
  11. package/__tests__/plugins-registry.test.js +44 -0
  12. package/__tests__/plugins-store.test.js +40 -5
  13. package/__tests__/process-adapter.test.js +50 -1
  14. package/__tests__/resend-plugin.test.js +22 -1
  15. package/__tests__/server-app.test.js +1 -0
  16. package/__tests__/server-routes-commands.test.js +20 -2
  17. package/__tests__/server-routes-plugins.test.js +130 -0
  18. package/__tests__/skills.test.js +26 -0
  19. package/__tests__/squirrelscan-plugin.test.js +129 -0
  20. package/__tests__/uipath-plugin.test.js +104 -0
  21. package/__tests__/uipathcli-plugin.test.js +95 -0
  22. package/cli/adapters/mcp.js +2 -0
  23. package/cli/adapters/process.js +49 -2
  24. package/cli/config.js +240 -3
  25. package/cli/discover.js +157 -0
  26. package/cli/help-json.js +16 -1
  27. package/cli/plugin-install-guidance.js +92 -37
  28. package/cli/plugins-manager.js +1 -0
  29. package/cli/plugins-registry.js +74 -8
  30. package/cli/plugins-store.js +78 -17
  31. package/cli/skills-mcp.js +1 -1
  32. package/cli/skills.js +39 -2
  33. package/cli/supercli.js +87 -11
  34. package/docs/feature-gaps.md +8 -8
  35. package/docs/features/azd-uipath-plugins.md +43 -0
  36. package/docs/features/server-plugins.md +62 -0
  37. package/docs/features/skills.md +9 -5
  38. package/docs/{supported-harnesses.md → plugins-available.md} +4 -3
  39. package/docs/{plugin-harness-guide.md → plugins-how-to.md} +1 -1
  40. package/docs/plugins.md +26 -20
  41. package/docs/server-plugins-usage-guide.md +182 -0
  42. package/docs/skills-catalog.md +12 -10
  43. package/package.json +1 -1
  44. package/plugins/agent-browser/README.md +69 -0
  45. package/plugins/agent-browser/plugin.json +111 -0
  46. package/plugins/agent-browser/skills/quickstart/SKILL.md +66 -0
  47. package/plugins/aider/README.md +53 -0
  48. package/plugins/aider/plugin.json +105 -0
  49. package/plugins/aider/scripts/aider-wrapper.js +243 -0
  50. package/plugins/aider/scripts/setup-aider.js +37 -0
  51. package/plugins/aider/skills/dry-run-review.md +24 -0
  52. package/plugins/aider/skills/model-and-provider.md +24 -0
  53. package/plugins/aider/skills/one-shot-edits.md +30 -0
  54. package/plugins/aider/skills/quickstart/SKILL.md +51 -0
  55. package/plugins/azd/README.md +28 -0
  56. package/plugins/azd/plugin.json +87 -0
  57. package/plugins/azd/skills/quickstart/SKILL.md +41 -0
  58. package/plugins/blogwatcher/README.md +3 -3
  59. package/plugins/boxlite/Dockerfile +9 -0
  60. package/plugins/boxlite/README.md +62 -0
  61. package/plugins/boxlite/plugin.json +201 -0
  62. package/plugins/boxlite/scripts/run-boxlite.js +106 -0
  63. package/plugins/boxlite/skills/quickstart/SKILL.md +40 -0
  64. package/plugins/cass/plugin.json +150 -0
  65. package/plugins/cass/scripts/setup-cass.js +47 -0
  66. package/plugins/cass/skills/quickstart/SKILL.md +46 -0
  67. package/plugins/clever/README.md +46 -0
  68. package/plugins/clever/plugin.json +119 -0
  69. package/plugins/clever/scripts/setup-clever.js +28 -0
  70. package/plugins/clever/skills/auth-and-profile.md +29 -0
  71. package/plugins/clever/skills/passthrough-safety.md +21 -0
  72. package/plugins/clever/skills/quickstart/SKILL.md +45 -0
  73. package/plugins/clever/skills/resource-inventory.md +24 -0
  74. package/plugins/clix/README.md +4 -4
  75. package/plugins/cocoindex-code/README.md +64 -0
  76. package/plugins/cocoindex-code/plugin.json +81 -0
  77. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-310.pyc +0 -0
  78. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-311.pyc +0 -0
  79. package/plugins/cocoindex-code/scripts/post-install.js +61 -0
  80. package/plugins/cocoindex-code/scripts/post-uninstall.js +25 -0
  81. package/plugins/cocoindex-code/scripts/query.py +88 -0
  82. package/plugins/cocoindex-code/scripts/run-query.js +50 -0
  83. package/plugins/cocoindex-code/skills/quickstart/SKILL.md +73 -0
  84. package/plugins/copilot/README.md +24 -0
  85. package/plugins/copilot/plugin.json +80 -0
  86. package/plugins/copilot/skills/quickstart/SKILL.md +44 -0
  87. package/plugins/gemini/README.md +24 -0
  88. package/plugins/gemini/plugin.json +98 -0
  89. package/plugins/gemini/skills/quickstart/SKILL.md +44 -0
  90. package/plugins/gifcap/plugin.json +119 -0
  91. package/plugins/gifcap/scripts/setup-gifcap.js +44 -0
  92. package/plugins/gifcap/skills/quickstart/SKILL.md +34 -0
  93. package/plugins/gifcap/test-record-quiet.gif +0 -0
  94. package/plugins/gifcap/test-record.gif +0 -0
  95. package/plugins/goose/README.md +36 -0
  96. package/plugins/goose/plugin.json +183 -0
  97. package/plugins/goose/skills/quickstart/SKILL.md +44 -0
  98. package/plugins/json-server/README.md +58 -0
  99. package/plugins/json-server/plugin.json +113 -0
  100. package/plugins/json-server/skills/quickstart/SKILL.md +57 -0
  101. package/plugins/lightpanda/README.md +145 -0
  102. package/plugins/lightpanda/package-lock.json +1375 -0
  103. package/plugins/lightpanda/package.json +12 -0
  104. package/plugins/lightpanda/plugin.json +116 -0
  105. package/plugins/lightpanda/scripts/lightpanda-contacts.js +494 -0
  106. package/plugins/lightpanda/scripts/lightpanda-generic-extract.js +403 -0
  107. package/plugins/lightpanda/scripts/lightpanda-wrapper.js +480 -0
  108. package/plugins/lightpanda/scripts/setup-lightpanda.js +39 -0
  109. package/plugins/lightpanda/skills/contact-discovery.md +51 -0
  110. package/plugins/lightpanda/skills/generic-extraction.md +66 -0
  111. package/plugins/lightpanda/skills/quickstart/SKILL.md +103 -0
  112. package/plugins/lightpanda/skills/resilient-navigation.md +42 -0
  113. package/plugins/monty/README.md +2 -2
  114. package/plugins/nullclaw/README.md +3 -3
  115. package/plugins/offline-ai/README.md +23 -0
  116. package/plugins/offline-ai/plugin.json +82 -0
  117. package/plugins/offline-ai/skills/quickstart/SKILL.md +43 -0
  118. package/plugins/openhands/README.md +25 -0
  119. package/plugins/openhands/plugin.json +116 -0
  120. package/plugins/openhands/skills/quickstart/SKILL.md +26 -0
  121. package/plugins/plandex/README.md +25 -0
  122. package/plugins/plandex/plugin.json +130 -0
  123. package/plugins/plandex/skills/quickstart/SKILL.md +50 -0
  124. package/plugins/plugins.json +190 -2
  125. package/plugins/resend/plugin.json +279 -2
  126. package/plugins/resend/skills/quickstart/SKILL.md +32 -13
  127. package/plugins/squirrelscan/Dockerfile +5 -0
  128. package/plugins/squirrelscan/README.md +47 -0
  129. package/plugins/squirrelscan/plugin.json +493 -0
  130. package/plugins/squirrelscan/scripts/post-install.js +33 -0
  131. package/plugins/squirrelscan/scripts/post-uninstall.js +25 -0
  132. package/plugins/squirrelscan/scripts/run-squirrel.js +73 -0
  133. package/plugins/squirrelscan/skills/audit-workflow/SKILL.md +33 -0
  134. package/plugins/squirrelscan/skills/publish-report/SKILL.md +33 -0
  135. package/plugins/squirrelscan/skills/quickstart/SKILL.md +41 -0
  136. package/plugins/uipath/README.md +27 -0
  137. package/plugins/uipath/plugin.json +86 -0
  138. package/plugins/uipath/skills/quickstart/SKILL.md +47 -0
  139. package/plugins/uipathcli/README.md +28 -0
  140. package/plugins/uipathcli/plugin.json +120 -0
  141. package/plugins/uipathcli/scripts/run-uipath-cli.js +49 -0
  142. package/plugins/uipathcli/skills/quickstart/SKILL.md +22 -0
  143. package/plugins/xurl/README.md +4 -4
  144. package/server/app.js +5 -2
  145. package/server/public/app.js +3 -0
  146. package/server/routes/commands.js +95 -12
  147. package/server/routes/plugins.js +262 -0
  148. package/server/services/pluginsService.js +303 -0
  149. package/server/views/command-edit.ejs +196 -14
  150. package/server/views/partials/head.ejs +1 -0
  151. package/server/views/plugins.ejs +264 -0
  152. package/tests/test-plugins-registry.js +30 -0
  153. package/tests/test-resend-smoke.sh +7 -3
  154. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl +0 -20
  155. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl.meta.json +0 -1
  156. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl +0 -21
  157. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl.meta.json +0 -1
  158. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl +0 -22
  159. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl.meta.json +0 -1
  160. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl +0 -23
  161. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl.meta.json +0 -1
  162. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl +0 -24
  163. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl.meta.json +0 -1
  164. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl +0 -24
  165. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl.meta.json +0 -1
  166. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl +0 -24
  167. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl.meta.json +0 -1
  168. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl +0 -24
  169. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl.meta.json +0 -1
  170. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl +0 -24
  171. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl.meta.json +0 -1
  172. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl +0 -24
  173. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl.meta.json +0 -1
  174. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl +0 -24
  175. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl.meta.json +0 -1
  176. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl +0 -24
  177. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl.meta.json +0 -1
  178. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl +0 -24
  179. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl.meta.json +0 -1
  180. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl +0 -25
  181. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl.meta.json +0 -1
  182. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl +0 -25
  183. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl.meta.json +0 -1
  184. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl +0 -25
  185. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl.meta.json +0 -1
  186. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl +0 -26
  187. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl.meta.json +0 -1
  188. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl +0 -27
  189. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl.meta.json +0 -1
  190. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl +0 -28
  191. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl.meta.json +0 -1
  192. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl +0 -29
  193. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl.meta.json +0 -1
  194. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl +0 -30
  195. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl.meta.json +0 -1
  196. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl +0 -31
  197. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl.meta.json +0 -1
  198. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl +0 -32
  199. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl.meta.json +0 -1
  200. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl +0 -32
  201. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl.meta.json +0 -1
  202. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl +0 -32
  203. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl.meta.json +0 -1
  204. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl +0 -32
  205. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl.meta.json +0 -1
  206. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl +0 -32
  207. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl.meta.json +0 -1
  208. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl +0 -32
  209. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl.meta.json +0 -1
  210. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl +0 -32
  211. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl.meta.json +0 -1
  212. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl +0 -32
  213. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl.meta.json +0 -1
  214. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl +0 -32
  215. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl.meta.json +0 -1
  216. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl +0 -32
  217. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl.meta.json +0 -1
  218. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl +0 -32
  219. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl.meta.json +0 -1
  220. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl +0 -32
  221. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl.meta.json +0 -1
  222. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl +0 -32
  223. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl.meta.json +0 -1
  224. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl +0 -32
  225. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl.meta.json +0 -1
  226. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl +0 -33
  227. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl.meta.json +0 -1
  228. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl +0 -33
  229. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl.meta.json +0 -1
  230. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl +0 -34
  231. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl.meta.json +0 -1
  232. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl +0 -34
  233. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl.meta.json +0 -1
  234. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl +0 -35
  235. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl.meta.json +0 -1
  236. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl +0 -36
  237. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl.meta.json +0 -1
  238. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl +0 -37
  239. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl.meta.json +0 -1
  240. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl +0 -38
  241. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl.meta.json +0 -1
  242. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl +0 -39
  243. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl.meta.json +0 -1
  244. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl +0 -40
  245. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl.meta.json +0 -1
  246. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl +0 -41
  247. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl.meta.json +0 -1
  248. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl +0 -42
  249. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl.meta.json +0 -1
  250. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl +0 -43
  251. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl.meta.json +0 -1
  252. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl +0 -44
  253. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl.meta.json +0 -1
  254. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl +0 -45
  255. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl.meta.json +0 -1
  256. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl +0 -46
  257. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl.meta.json +0 -1
  258. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl +0 -47
  259. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl.meta.json +0 -1
  260. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl +0 -48
  261. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl.meta.json +0 -1
  262. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl +0 -49
  263. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl.meta.json +0 -1
  264. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl +0 -50
  265. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl.meta.json +0 -1
  266. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl +0 -51
  267. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl.meta.json +0 -1
  268. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl +0 -52
  269. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl.meta.json +0 -1
  270. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl +0 -53
  271. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl.meta.json +0 -1
  272. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl +0 -54
  273. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl.meta.json +0 -1
  274. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl +0 -55
  275. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl.meta.json +0 -1
  276. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl +0 -56
  277. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl.meta.json +0 -1
  278. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl +0 -57
  279. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl.meta.json +0 -1
  280. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl +0 -57
  281. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl.meta.json +0 -1
  282. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl +0 -57
  283. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl.meta.json +0 -1
  284. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl +0 -57
  285. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl.meta.json +0 -1
  286. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl +0 -57
  287. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl.meta.json +0 -1
  288. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl +0 -57
  289. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl.meta.json +0 -1
  290. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl +0 -57
  291. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl.meta.json +0 -1
  292. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl +0 -57
  293. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl.meta.json +0 -1
  294. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl +0 -57
  295. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl.meta.json +0 -1
  296. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl +0 -57
  297. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl.meta.json +0 -1
  298. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl +0 -57
  299. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl.meta.json +0 -1
  300. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl +0 -57
  301. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl.meta.json +0 -1
  302. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl +0 -57
  303. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl.meta.json +0 -1
  304. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl +0 -57
  305. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl.meta.json +0 -1
  306. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl +0 -57
  307. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl.meta.json +0 -1
  308. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl +0 -57
  309. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl.meta.json +0 -1
  310. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl +0 -57
  311. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl.meta.json +0 -1
  312. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl +0 -57
  313. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl.meta.json +0 -1
  314. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl +0 -57
  315. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl.meta.json +0 -1
  316. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl +0 -57
  317. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl.meta.json +0 -1
  318. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl +0 -57
  319. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl.meta.json +0 -1
  320. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl +0 -57
  321. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl.meta.json +0 -1
  322. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl +0 -57
  323. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl.meta.json +0 -1
  324. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl +0 -57
  325. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl.meta.json +0 -1
  326. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl +0 -57
  327. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl.meta.json +0 -1
  328. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl +0 -57
  329. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl.meta.json +0 -1
  330. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl +0 -57
  331. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl.meta.json +0 -1
  332. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl +0 -57
  333. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl.meta.json +0 -1
  334. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl +0 -57
  335. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl.meta.json +0 -1
  336. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl +0 -57
  337. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl.meta.json +0 -1
  338. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl +0 -58
  339. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl.meta.json +0 -1
  340. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl +0 -59
  341. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl.meta.json +0 -1
  342. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl +0 -60
  343. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl.meta.json +0 -1
  344. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl +0 -60
  345. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl.meta.json +0 -1
  346. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl +0 -60
  347. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl.meta.json +0 -1
  348. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl +0 -60
  349. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl.meta.json +0 -1
  350. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl +0 -60
  351. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl.meta.json +0 -1
  352. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl +0 -60
  353. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl.meta.json +0 -1
  354. package/.beads/config.yaml +0 -4
  355. package/.beads/issues.jsonl +0 -60
  356. package/.beads/metadata.json +0 -4
  357. package/docs/mcp-cheatsheet.md +0 -324
  358. package/docs/visual-overview.md +0 -21
  359. package/ref-monty/.cargo/config.toml +0 -3
  360. package/ref-monty/.claude/settings.json +0 -60
  361. package/ref-monty/.claude/skills/fastmod/SKILL.md +0 -22
  362. package/ref-monty/.claude/skills/python-playground/SKILL.md +0 -47
  363. package/ref-monty/.codecov.yml +0 -12
  364. package/ref-monty/.github/actions/build-pgo-wheel/action.yml +0 -72
  365. package/ref-monty/.github/workflows/ci.yml +0 -776
  366. package/ref-monty/.github/workflows/codspeed.yml +0 -45
  367. package/ref-monty/.github/workflows/init-npm-packages.yml +0 -82
  368. package/ref-monty/.pre-commit-config.yaml +0 -47
  369. package/ref-monty/.python-version +0 -1
  370. package/ref-monty/.rustfmt.toml +0 -4
  371. package/ref-monty/.zed/settings.json +0 -11
  372. package/ref-monty/CLAUDE.md +0 -535
  373. package/ref-monty/Cargo.lock +0 -3798
  374. package/ref-monty/Cargo.toml +0 -87
  375. package/ref-monty/LICENSE +0 -21
  376. package/ref-monty/Makefile +0 -216
  377. package/ref-monty/README.md +0 -430
  378. package/ref-monty/RELEASING.md +0 -47
  379. package/ref-monty/crates/fuzz/Cargo.toml +0 -30
  380. package/ref-monty/crates/fuzz/fuzz_targets/string_input_panic.rs +0 -37
  381. package/ref-monty/crates/fuzz/fuzz_targets/tokens_input_panic.rs +0 -552
  382. package/ref-monty/crates/monty/Cargo.toml +0 -68
  383. package/ref-monty/crates/monty/benches/main.rs +0 -247
  384. package/ref-monty/crates/monty/build.rs +0 -10
  385. package/ref-monty/crates/monty/src/args.rs +0 -733
  386. package/ref-monty/crates/monty/src/asyncio.rs +0 -179
  387. package/ref-monty/crates/monty/src/builtins/abs.rs +0 -55
  388. package/ref-monty/crates/monty/src/builtins/all.rs +0 -30
  389. package/ref-monty/crates/monty/src/builtins/any.rs +0 -30
  390. package/ref-monty/crates/monty/src/builtins/bin.rs +0 -59
  391. package/ref-monty/crates/monty/src/builtins/chr.rs +0 -46
  392. package/ref-monty/crates/monty/src/builtins/divmod.rs +0 -164
  393. package/ref-monty/crates/monty/src/builtins/enumerate.rs +0 -52
  394. package/ref-monty/crates/monty/src/builtins/filter.rs +0 -67
  395. package/ref-monty/crates/monty/src/builtins/getattr.rs +0 -65
  396. package/ref-monty/crates/monty/src/builtins/hash.rs +0 -28
  397. package/ref-monty/crates/monty/src/builtins/hex.rs +0 -58
  398. package/ref-monty/crates/monty/src/builtins/id.rs +0 -24
  399. package/ref-monty/crates/monty/src/builtins/isinstance.rs +0 -68
  400. package/ref-monty/crates/monty/src/builtins/len.rs +0 -25
  401. package/ref-monty/crates/monty/src/builtins/map.rs +0 -98
  402. package/ref-monty/crates/monty/src/builtins/min_max.rs +0 -113
  403. package/ref-monty/crates/monty/src/builtins/mod.rs +0 -246
  404. package/ref-monty/crates/monty/src/builtins/next.rs +0 -21
  405. package/ref-monty/crates/monty/src/builtins/oct.rs +0 -59
  406. package/ref-monty/crates/monty/src/builtins/ord.rs +0 -67
  407. package/ref-monty/crates/monty/src/builtins/pow.rs +0 -365
  408. package/ref-monty/crates/monty/src/builtins/print.rs +0 -141
  409. package/ref-monty/crates/monty/src/builtins/repr.rs +0 -16
  410. package/ref-monty/crates/monty/src/builtins/reversed.rs +0 -28
  411. package/ref-monty/crates/monty/src/builtins/round.rs +0 -174
  412. package/ref-monty/crates/monty/src/builtins/sorted.rs +0 -151
  413. package/ref-monty/crates/monty/src/builtins/sum.rs +0 -66
  414. package/ref-monty/crates/monty/src/builtins/type_.rs +0 -16
  415. package/ref-monty/crates/monty/src/builtins/zip.rs +0 -77
  416. package/ref-monty/crates/monty/src/bytecode/builder.rs +0 -699
  417. package/ref-monty/crates/monty/src/bytecode/code.rs +0 -310
  418. package/ref-monty/crates/monty/src/bytecode/compiler.rs +0 -3206
  419. package/ref-monty/crates/monty/src/bytecode/mod.rs +0 -24
  420. package/ref-monty/crates/monty/src/bytecode/op.rs +0 -617
  421. package/ref-monty/crates/monty/src/bytecode/vm/async_exec.rs +0 -1058
  422. package/ref-monty/crates/monty/src/bytecode/vm/attr.rs +0 -63
  423. package/ref-monty/crates/monty/src/bytecode/vm/binary.rs +0 -487
  424. package/ref-monty/crates/monty/src/bytecode/vm/call.rs +0 -767
  425. package/ref-monty/crates/monty/src/bytecode/vm/collections.rs +0 -741
  426. package/ref-monty/crates/monty/src/bytecode/vm/compare.rs +0 -147
  427. package/ref-monty/crates/monty/src/bytecode/vm/exceptions.rs +0 -297
  428. package/ref-monty/crates/monty/src/bytecode/vm/format.rs +0 -132
  429. package/ref-monty/crates/monty/src/bytecode/vm/mod.rs +0 -1958
  430. package/ref-monty/crates/monty/src/bytecode/vm/scheduler.rs +0 -620
  431. package/ref-monty/crates/monty/src/exception_private.rs +0 -1513
  432. package/ref-monty/crates/monty/src/exception_public.rs +0 -346
  433. package/ref-monty/crates/monty/src/expressions.rs +0 -694
  434. package/ref-monty/crates/monty/src/fstring.rs +0 -854
  435. package/ref-monty/crates/monty/src/function.rs +0 -119
  436. package/ref-monty/crates/monty/src/heap.rs +0 -1073
  437. package/ref-monty/crates/monty/src/heap_data.rs +0 -985
  438. package/ref-monty/crates/monty/src/heap_traits.rs +0 -312
  439. package/ref-monty/crates/monty/src/intern.rs +0 -837
  440. package/ref-monty/crates/monty/src/io.rs +0 -106
  441. package/ref-monty/crates/monty/src/lib.rs +0 -52
  442. package/ref-monty/crates/monty/src/modules/asyncio.rs +0 -144
  443. package/ref-monty/crates/monty/src/modules/math.rs +0 -1453
  444. package/ref-monty/crates/monty/src/modules/mod.rs +0 -120
  445. package/ref-monty/crates/monty/src/modules/os.rs +0 -116
  446. package/ref-monty/crates/monty/src/modules/pathlib.rs +0 -33
  447. package/ref-monty/crates/monty/src/modules/re.rs +0 -606
  448. package/ref-monty/crates/monty/src/modules/sys.rs +0 -60
  449. package/ref-monty/crates/monty/src/modules/typing.rs +0 -70
  450. package/ref-monty/crates/monty/src/namespace.rs +0 -21
  451. package/ref-monty/crates/monty/src/object.rs +0 -1040
  452. package/ref-monty/crates/monty/src/os.rs +0 -215
  453. package/ref-monty/crates/monty/src/parse.rs +0 -1730
  454. package/ref-monty/crates/monty/src/prepare.rs +0 -3015
  455. package/ref-monty/crates/monty/src/repl.rs +0 -1109
  456. package/ref-monty/crates/monty/src/resource.rs +0 -559
  457. package/ref-monty/crates/monty/src/run.rs +0 -457
  458. package/ref-monty/crates/monty/src/run_progress.rs +0 -821
  459. package/ref-monty/crates/monty/src/signature.rs +0 -651
  460. package/ref-monty/crates/monty/src/sorting.rs +0 -100
  461. package/ref-monty/crates/monty/src/types/bytes.rs +0 -2356
  462. package/ref-monty/crates/monty/src/types/dataclass.rs +0 -345
  463. package/ref-monty/crates/monty/src/types/dict.rs +0 -879
  464. package/ref-monty/crates/monty/src/types/dict_view.rs +0 -619
  465. package/ref-monty/crates/monty/src/types/iter.rs +0 -799
  466. package/ref-monty/crates/monty/src/types/list.rs +0 -929
  467. package/ref-monty/crates/monty/src/types/long_int.rs +0 -211
  468. package/ref-monty/crates/monty/src/types/mod.rs +0 -48
  469. package/ref-monty/crates/monty/src/types/module.rs +0 -146
  470. package/ref-monty/crates/monty/src/types/namedtuple.rs +0 -261
  471. package/ref-monty/crates/monty/src/types/path.rs +0 -596
  472. package/ref-monty/crates/monty/src/types/property.rs +0 -35
  473. package/ref-monty/crates/monty/src/types/py_trait.rs +0 -322
  474. package/ref-monty/crates/monty/src/types/range.rs +0 -285
  475. package/ref-monty/crates/monty/src/types/re_match.rs +0 -522
  476. package/ref-monty/crates/monty/src/types/re_pattern.rs +0 -726
  477. package/ref-monty/crates/monty/src/types/set.rs +0 -1373
  478. package/ref-monty/crates/monty/src/types/slice.rs +0 -257
  479. package/ref-monty/crates/monty/src/types/str.rs +0 -2051
  480. package/ref-monty/crates/monty/src/types/tuple.rs +0 -376
  481. package/ref-monty/crates/monty/src/types/type.rs +0 -407
  482. package/ref-monty/crates/monty/src/value.rs +0 -2558
  483. package/ref-monty/crates/monty/test_cases/args__dict_get_no_args.py +0 -3
  484. package/ref-monty/crates/monty/test_cases/args__dict_get_too_many.py +0 -3
  485. package/ref-monty/crates/monty/test_cases/args__dict_items_with_args.py +0 -3
  486. package/ref-monty/crates/monty/test_cases/args__dict_keys_with_args.py +0 -3
  487. package/ref-monty/crates/monty/test_cases/args__dict_pop_no_args.py +0 -3
  488. package/ref-monty/crates/monty/test_cases/args__dict_pop_too_many.py +0 -3
  489. package/ref-monty/crates/monty/test_cases/args__dict_values_with_args.py +0 -3
  490. package/ref-monty/crates/monty/test_cases/args__id_too_many.py +0 -2
  491. package/ref-monty/crates/monty/test_cases/args__len_no_args.py +0 -2
  492. package/ref-monty/crates/monty/test_cases/args__len_too_many.py +0 -2
  493. package/ref-monty/crates/monty/test_cases/args__len_type_error_int.py +0 -9
  494. package/ref-monty/crates/monty/test_cases/args__len_type_error_none.py +0 -9
  495. package/ref-monty/crates/monty/test_cases/args__list_append_no_args.py +0 -3
  496. package/ref-monty/crates/monty/test_cases/args__list_append_too_many.py +0 -3
  497. package/ref-monty/crates/monty/test_cases/args__list_insert_too_few.py +0 -3
  498. package/ref-monty/crates/monty/test_cases/args__list_insert_too_many.py +0 -3
  499. package/ref-monty/crates/monty/test_cases/args__repr_no_args.py +0 -2
  500. package/ref-monty/crates/monty/test_cases/arith__div_zero_float.py +0 -2
  501. package/ref-monty/crates/monty/test_cases/arith__div_zero_int.py +0 -2
  502. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_float.py +0 -2
  503. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_int.py +0 -2
  504. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg.py +0 -2
  505. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg_builtin.py +0 -9
  506. package/ref-monty/crates/monty/test_cases/assert__expr_fail.py +0 -2
  507. package/ref-monty/crates/monty/test_cases/assert__fail.py +0 -2
  508. package/ref-monty/crates/monty/test_cases/assert__fail_msg.py +0 -2
  509. package/ref-monty/crates/monty/test_cases/assert__fn_fail.py +0 -3
  510. package/ref-monty/crates/monty/test_cases/assert__ops.py +0 -11
  511. package/ref-monty/crates/monty/test_cases/async__asyncio_run.py +0 -47
  512. package/ref-monty/crates/monty/test_cases/async__basic.py +0 -10
  513. package/ref-monty/crates/monty/test_cases/async__closure.py +0 -14
  514. package/ref-monty/crates/monty/test_cases/async__double_await_coroutine.py +0 -16
  515. package/ref-monty/crates/monty/test_cases/async__exception.py +0 -10
  516. package/ref-monty/crates/monty/test_cases/async__ext_call.py +0 -73
  517. package/ref-monty/crates/monty/test_cases/async__gather_all.py +0 -85
  518. package/ref-monty/crates/monty/test_cases/async__nested_await.py +0 -15
  519. package/ref-monty/crates/monty/test_cases/async__nested_gather_ext.py +0 -37
  520. package/ref-monty/crates/monty/test_cases/async__not_awaitable.py +0 -10
  521. package/ref-monty/crates/monty/test_cases/async__not_imported.py +0 -14
  522. package/ref-monty/crates/monty/test_cases/async__recursion_depth_isolation.py +0 -27
  523. package/ref-monty/crates/monty/test_cases/async__return_types.py +0 -31
  524. package/ref-monty/crates/monty/test_cases/async__sequential.py +0 -16
  525. package/ref-monty/crates/monty/test_cases/async__traceback.py +0 -19
  526. package/ref-monty/crates/monty/test_cases/async__with_args.py +0 -14
  527. package/ref-monty/crates/monty/test_cases/attr__get_int_error.py +0 -9
  528. package/ref-monty/crates/monty/test_cases/attr__get_list_error.py +0 -9
  529. package/ref-monty/crates/monty/test_cases/attr__set_frozen_nonfield.py +0 -12
  530. package/ref-monty/crates/monty/test_cases/attr__set_int_error.py +0 -10
  531. package/ref-monty/crates/monty/test_cases/attr__set_list_error.py +0 -10
  532. package/ref-monty/crates/monty/test_cases/bench__kitchen_sink.py +0 -68
  533. package/ref-monty/crates/monty/test_cases/bool__ops.py +0 -20
  534. package/ref-monty/crates/monty/test_cases/builtin__add_type_error.py +0 -2
  535. package/ref-monty/crates/monty/test_cases/builtin__filter.py +0 -62
  536. package/ref-monty/crates/monty/test_cases/builtin__filter_not_iterable.py +0 -11
  537. package/ref-monty/crates/monty/test_cases/builtin__getattr.py +0 -84
  538. package/ref-monty/crates/monty/test_cases/builtin__iter_funcs.py +0 -42
  539. package/ref-monty/crates/monty/test_cases/builtin__iter_next.py +0 -66
  540. package/ref-monty/crates/monty/test_cases/builtin__map.py +0 -74
  541. package/ref-monty/crates/monty/test_cases/builtin__map_not_iterable.py +0 -11
  542. package/ref-monty/crates/monty/test_cases/builtin__math_funcs.py +0 -154
  543. package/ref-monty/crates/monty/test_cases/builtin__more_iter_funcs.py +0 -148
  544. package/ref-monty/crates/monty/test_cases/builtin__next_stop_iteration.py +0 -10
  545. package/ref-monty/crates/monty/test_cases/builtin__print_invalid_kwarg.py +0 -9
  546. package/ref-monty/crates/monty/test_cases/builtin__print_kwargs.py +0 -12
  547. package/ref-monty/crates/monty/test_cases/builtin__repr.py +0 -3
  548. package/ref-monty/crates/monty/test_cases/builtin__string_funcs.py +0 -73
  549. package/ref-monty/crates/monty/test_cases/bytes__decode_invalid_utf8.py +0 -18
  550. package/ref-monty/crates/monty/test_cases/bytes__endswith_str_error.py +0 -10
  551. package/ref-monty/crates/monty/test_cases/bytes__getitem_index_error.py +0 -10
  552. package/ref-monty/crates/monty/test_cases/bytes__index_start_gt_end.py +0 -10
  553. package/ref-monty/crates/monty/test_cases/bytes__methods.py +0 -394
  554. package/ref-monty/crates/monty/test_cases/bytes__negative_count.py +0 -9
  555. package/ref-monty/crates/monty/test_cases/bytes__ops.py +0 -90
  556. package/ref-monty/crates/monty/test_cases/bytes__startswith_str_error.py +0 -10
  557. package/ref-monty/crates/monty/test_cases/call_object.py +0 -3
  558. package/ref-monty/crates/monty/test_cases/chain_comparison__all.py +0 -79
  559. package/ref-monty/crates/monty/test_cases/closure__param_shadows_outer.py +0 -81
  560. package/ref-monty/crates/monty/test_cases/closure__pep448.py +0 -203
  561. package/ref-monty/crates/monty/test_cases/closure__undefined_nonlocal.py +0 -13
  562. package/ref-monty/crates/monty/test_cases/compare__mixed_types.py +0 -120
  563. package/ref-monty/crates/monty/test_cases/comprehension__all.py +0 -208
  564. package/ref-monty/crates/monty/test_cases/comprehension__scope.py +0 -7
  565. package/ref-monty/crates/monty/test_cases/comprehension__unbound_local.py +0 -14
  566. package/ref-monty/crates/monty/test_cases/dataclass__basic.py +0 -238
  567. package/ref-monty/crates/monty/test_cases/dataclass__call_field_error.py +0 -12
  568. package/ref-monty/crates/monty/test_cases/dataclass__frozen_set_error.py +0 -12
  569. package/ref-monty/crates/monty/test_cases/dataclass__get_missing_attr_error.py +0 -11
  570. package/ref-monty/crates/monty/test_cases/dict__get_unhashable_key.py +0 -3
  571. package/ref-monty/crates/monty/test_cases/dict__literal_unhashable_key.py +0 -2
  572. package/ref-monty/crates/monty/test_cases/dict__method_pop_missing_error.py +0 -3
  573. package/ref-monty/crates/monty/test_cases/dict__methods.py +0 -151
  574. package/ref-monty/crates/monty/test_cases/dict__ops.py +0 -133
  575. package/ref-monty/crates/monty/test_cases/dict__pop_unhashable_key.py +0 -4
  576. package/ref-monty/crates/monty/test_cases/dict__popitem_empty.py +0 -9
  577. package/ref-monty/crates/monty/test_cases/dict__subscript_missing_key.py +0 -3
  578. package/ref-monty/crates/monty/test_cases/dict__unhashable_dict_key.py +0 -2
  579. package/ref-monty/crates/monty/test_cases/dict__unhashable_list_key.py +0 -2
  580. package/ref-monty/crates/monty/test_cases/dict__unpack_type_error.py +0 -2
  581. package/ref-monty/crates/monty/test_cases/dict__views.py +0 -165
  582. package/ref-monty/crates/monty/test_cases/edge__all.py +0 -26
  583. package/ref-monty/crates/monty/test_cases/edge__float_int_mod.py +0 -2
  584. package/ref-monty/crates/monty/test_cases/edge__int_float_mod.py +0 -2
  585. package/ref-monty/crates/monty/test_cases/exc__args.py +0 -16
  586. package/ref-monty/crates/monty/test_cases/exc__str.py +0 -15
  587. package/ref-monty/crates/monty/test_cases/execute_ok__all.py +0 -54
  588. package/ref-monty/crates/monty/test_cases/execute_raise__error_instance_str.py +0 -2
  589. package/ref-monty/crates/monty/test_cases/execute_raise__error_no_args.py +0 -2
  590. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg.py +0 -2
  591. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg_quotes.py +0 -2
  592. package/ref-monty/crates/monty/test_cases/execute_raise__error_type.py +0 -2
  593. package/ref-monty/crates/monty/test_cases/execute_raise__raise_instance_via_var.py +0 -4
  594. package/ref-monty/crates/monty/test_cases/execute_raise__raise_list.py +0 -2
  595. package/ref-monty/crates/monty/test_cases/execute_raise__raise_number.py +0 -2
  596. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_call_via_var.py +0 -4
  597. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_direct.py +0 -3
  598. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_via_var.py +0 -4
  599. package/ref-monty/crates/monty/test_cases/ext_call__arg_side_effect_bug.py +0 -22
  600. package/ref-monty/crates/monty/test_cases/ext_call__augmented.py +0 -17
  601. package/ref-monty/crates/monty/test_cases/ext_call__augmented_refcount_bug.py +0 -7
  602. package/ref-monty/crates/monty/test_cases/ext_call__bare_raise_after_resume.py +0 -34
  603. package/ref-monty/crates/monty/test_cases/ext_call__basic.py +0 -99
  604. package/ref-monty/crates/monty/test_cases/ext_call__boolean.py +0 -37
  605. package/ref-monty/crates/monty/test_cases/ext_call__boolean_side_effect_hang.py +0 -17
  606. package/ref-monty/crates/monty/test_cases/ext_call__closure_bug.py +0 -16
  607. package/ref-monty/crates/monty/test_cases/ext_call__comparison.py +0 -26
  608. package/ref-monty/crates/monty/test_cases/ext_call__deep_call_stack.py +0 -18
  609. package/ref-monty/crates/monty/test_cases/ext_call__elif.py +0 -171
  610. package/ref-monty/crates/monty/test_cases/ext_call__exc.py +0 -4
  611. package/ref-monty/crates/monty/test_cases/ext_call__exc_deep_stack.py +0 -39
  612. package/ref-monty/crates/monty/test_cases/ext_call__exc_in_function.py +0 -17
  613. package/ref-monty/crates/monty/test_cases/ext_call__exc_nested_functions.py +0 -31
  614. package/ref-monty/crates/monty/test_cases/ext_call__ext_exc.py +0 -171
  615. package/ref-monty/crates/monty/test_cases/ext_call__for.py +0 -114
  616. package/ref-monty/crates/monty/test_cases/ext_call__fstring.py +0 -12
  617. package/ref-monty/crates/monty/test_cases/ext_call__if.py +0 -135
  618. package/ref-monty/crates/monty/test_cases/ext_call__if_condition.py +0 -37
  619. package/ref-monty/crates/monty/test_cases/ext_call__in_closure.py +0 -14
  620. package/ref-monty/crates/monty/test_cases/ext_call__in_function.py +0 -40
  621. package/ref-monty/crates/monty/test_cases/ext_call__in_function_simple.py +0 -7
  622. package/ref-monty/crates/monty/test_cases/ext_call__literals.py +0 -17
  623. package/ref-monty/crates/monty/test_cases/ext_call__multi_in_func.py +0 -32
  624. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup.py +0 -69
  625. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup_undefined.py +0 -4
  626. package/ref-monty/crates/monty/test_cases/ext_call__nested_calls.py +0 -14
  627. package/ref-monty/crates/monty/test_cases/ext_call__recursion_bug.py +0 -19
  628. package/ref-monty/crates/monty/test_cases/ext_call__return.py +0 -28
  629. package/ref-monty/crates/monty/test_cases/ext_call__side_effects.py +0 -25
  630. package/ref-monty/crates/monty/test_cases/ext_call__subscript.py +0 -7
  631. package/ref-monty/crates/monty/test_cases/ext_call__ternary.py +0 -28
  632. package/ref-monty/crates/monty/test_cases/ext_call__try.py +0 -280
  633. package/ref-monty/crates/monty/test_cases/ext_call__try_simple.py +0 -10
  634. package/ref-monty/crates/monty/test_cases/ext_call__unary.py +0 -13
  635. package/ref-monty/crates/monty/test_cases/frozenset__ops.py +0 -178
  636. package/ref-monty/crates/monty/test_cases/fstring__all.py +0 -236
  637. package/ref-monty/crates/monty/test_cases/fstring__error_eq_align_on_str.py +0 -3
  638. package/ref-monty/crates/monty/test_cases/fstring__error_float_f_on_str.py +0 -3
  639. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_float.py +0 -3
  640. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_str.py +0 -3
  641. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec.py +0 -4
  642. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_dynamic.py +0 -4
  643. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_str.py +0 -4
  644. package/ref-monty/crates/monty/test_cases/fstring__error_str_s_on_int.py +0 -3
  645. package/ref-monty/crates/monty/test_cases/function__call_duplicate_kwargs.py +0 -6
  646. package/ref-monty/crates/monty/test_cases/function__call_unpack.py +0 -42
  647. package/ref-monty/crates/monty/test_cases/function__defaults.py +0 -117
  648. package/ref-monty/crates/monty/test_cases/function__err_duplicate_arg.py +0 -7
  649. package/ref-monty/crates/monty/test_cases/function__err_duplicate_first_arg.py +0 -7
  650. package/ref-monty/crates/monty/test_cases/function__err_duplicate_kwarg_cleanup.py +0 -9
  651. package/ref-monty/crates/monty/test_cases/function__err_kwonly_as_positional.py +0 -7
  652. package/ref-monty/crates/monty/test_cases/function__err_missing_all_posonly.py +0 -7
  653. package/ref-monty/crates/monty/test_cases/function__err_missing_heap_cleanup.py +0 -9
  654. package/ref-monty/crates/monty/test_cases/function__err_missing_kwonly.py +0 -7
  655. package/ref-monty/crates/monty/test_cases/function__err_missing_posonly_with_kwarg.py +0 -7
  656. package/ref-monty/crates/monty/test_cases/function__err_missing_with_posonly.py +0 -7
  657. package/ref-monty/crates/monty/test_cases/function__err_posonly_as_kwarg.py +0 -7
  658. package/ref-monty/crates/monty/test_cases/function__err_posonly_first_as_kwarg.py +0 -7
  659. package/ref-monty/crates/monty/test_cases/function__err_too_many_posonly.py +0 -7
  660. package/ref-monty/crates/monty/test_cases/function__err_too_many_with_kwonly.py +0 -7
  661. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg.py +0 -7
  662. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_cleanup.py +0 -9
  663. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_quote.py +0 -13
  664. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_simple.py +0 -7
  665. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_arg.py +0 -6
  666. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_heap.py +0 -8
  667. package/ref-monty/crates/monty/test_cases/function__err_unpack_int.py +0 -6
  668. package/ref-monty/crates/monty/test_cases/function__err_unpack_nonstring_key.py +0 -6
  669. package/ref-monty/crates/monty/test_cases/function__err_unpack_not_mapping.py +0 -6
  670. package/ref-monty/crates/monty/test_cases/function__kwargs_unpacking.py +0 -173
  671. package/ref-monty/crates/monty/test_cases/function__ops.py +0 -294
  672. package/ref-monty/crates/monty/test_cases/function__return_none.py +0 -42
  673. package/ref-monty/crates/monty/test_cases/function__signatures.py +0 -47
  674. package/ref-monty/crates/monty/test_cases/function__too_few_args_all.py +0 -6
  675. package/ref-monty/crates/monty/test_cases/function__too_few_args_one.py +0 -6
  676. package/ref-monty/crates/monty/test_cases/function__too_few_args_two.py +0 -6
  677. package/ref-monty/crates/monty/test_cases/function__too_many_args_one.py +0 -6
  678. package/ref-monty/crates/monty/test_cases/function__too_many_args_two.py +0 -6
  679. package/ref-monty/crates/monty/test_cases/function__too_many_args_zero.py +0 -6
  680. package/ref-monty/crates/monty/test_cases/global__error_assigned_before.py +0 -7
  681. package/ref-monty/crates/monty/test_cases/global__ops.py +0 -163
  682. package/ref-monty/crates/monty/test_cases/hash__dict_unhashable.py +0 -2
  683. package/ref-monty/crates/monty/test_cases/hash__list_unhashable.py +0 -2
  684. package/ref-monty/crates/monty/test_cases/hash__ops.py +0 -153
  685. package/ref-monty/crates/monty/test_cases/id__bytes_literals_distinct.py +0 -3
  686. package/ref-monty/crates/monty/test_cases/id__int_copy_distinct.py +0 -5
  687. package/ref-monty/crates/monty/test_cases/id__is_number_is_number.py +0 -3
  688. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_distinct_types.py +0 -10
  689. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_same_types.py +0 -6
  690. package/ref-monty/crates/monty/test_cases/id__ops.py +0 -97
  691. package/ref-monty/crates/monty/test_cases/id__str_literals_same.py +0 -3
  692. package/ref-monty/crates/monty/test_cases/if__elif_else.py +0 -207
  693. package/ref-monty/crates/monty/test_cases/if__raise_elif.py +0 -11
  694. package/ref-monty/crates/monty/test_cases/if__raise_else.py +0 -13
  695. package/ref-monty/crates/monty/test_cases/if__raise_if.py +0 -9
  696. package/ref-monty/crates/monty/test_cases/if__raise_in_elif_condition.py +0 -18
  697. package/ref-monty/crates/monty/test_cases/if__raise_in_if_condition.py +0 -16
  698. package/ref-monty/crates/monty/test_cases/if_else_expr__all.py +0 -55
  699. package/ref-monty/crates/monty/test_cases/import__error_cannot_import.py +0 -9
  700. package/ref-monty/crates/monty/test_cases/import__error_module_not_found.py +0 -9
  701. package/ref-monty/crates/monty/test_cases/import__local_scope.py +0 -68
  702. package/ref-monty/crates/monty/test_cases/import__os.py +0 -25
  703. package/ref-monty/crates/monty/test_cases/import__relative_error.py +0 -9
  704. package/ref-monty/crates/monty/test_cases/import__relative_no_module_error.py +0 -9
  705. package/ref-monty/crates/monty/test_cases/import__runtime_error_when_executed.py +0 -14
  706. package/ref-monty/crates/monty/test_cases/import__star_error.py +0 -11
  707. package/ref-monty/crates/monty/test_cases/import__sys.py +0 -47
  708. package/ref-monty/crates/monty/test_cases/import__sys_monty.py +0 -28
  709. package/ref-monty/crates/monty/test_cases/import__type_checking_guard.py +0 -37
  710. package/ref-monty/crates/monty/test_cases/import__typing.py +0 -25
  711. package/ref-monty/crates/monty/test_cases/import__typing_type_ignore.py +0 -4
  712. package/ref-monty/crates/monty/test_cases/int__bigint.py +0 -467
  713. package/ref-monty/crates/monty/test_cases/int__bigint_errors.py +0 -260
  714. package/ref-monty/crates/monty/test_cases/int__ops.py +0 -219
  715. package/ref-monty/crates/monty/test_cases/int__overflow_division.py +0 -84
  716. package/ref-monty/crates/monty/test_cases/is_variant__all.py +0 -36
  717. package/ref-monty/crates/monty/test_cases/isinstance__arg2_list_error.py +0 -2
  718. package/ref-monty/crates/monty/test_cases/isinstance__arg2_type_error.py +0 -2
  719. package/ref-monty/crates/monty/test_cases/iter__dict_mutation.py +0 -4
  720. package/ref-monty/crates/monty/test_cases/iter__for.py +0 -243
  721. package/ref-monty/crates/monty/test_cases/iter__for_loop_unpacking.py +0 -66
  722. package/ref-monty/crates/monty/test_cases/iter__generator_expr.py +0 -20
  723. package/ref-monty/crates/monty/test_cases/iter__generator_expr_type.py +0 -7
  724. package/ref-monty/crates/monty/test_cases/iter__not_iterable.py +0 -3
  725. package/ref-monty/crates/monty/test_cases/lambda__all.py +0 -145
  726. package/ref-monty/crates/monty/test_cases/list__extend_not_iterable.py +0 -7
  727. package/ref-monty/crates/monty/test_cases/list__getitem_out_of_bounds.py +0 -3
  728. package/ref-monty/crates/monty/test_cases/list__index_not_found.py +0 -9
  729. package/ref-monty/crates/monty/test_cases/list__index_start_gt_end.py +0 -10
  730. package/ref-monty/crates/monty/test_cases/list__ops.py +0 -473
  731. package/ref-monty/crates/monty/test_cases/list__pop_empty.py +0 -9
  732. package/ref-monty/crates/monty/test_cases/list__pop_out_of_range.py +0 -9
  733. package/ref-monty/crates/monty/test_cases/list__pop_type_error.py +0 -9
  734. package/ref-monty/crates/monty/test_cases/list__remove_not_found.py +0 -9
  735. package/ref-monty/crates/monty/test_cases/list__setitem_dict_index.py +0 -13
  736. package/ref-monty/crates/monty/test_cases/list__setitem_huge_int_index.py +0 -13
  737. package/ref-monty/crates/monty/test_cases/list__setitem_index_error.py +0 -10
  738. package/ref-monty/crates/monty/test_cases/list__setitem_type_error.py +0 -10
  739. package/ref-monty/crates/monty/test_cases/list__unpack_type_error.py +0 -2
  740. package/ref-monty/crates/monty/test_cases/longint__index_error.py +0 -3
  741. package/ref-monty/crates/monty/test_cases/longint__repeat_error.py +0 -3
  742. package/ref-monty/crates/monty/test_cases/loop__break_continue.py +0 -113
  743. package/ref-monty/crates/monty/test_cases/loop__break_finally.py +0 -69
  744. package/ref-monty/crates/monty/test_cases/loop__break_in_function_error.py +0 -13
  745. package/ref-monty/crates/monty/test_cases/loop__break_in_if_error.py +0 -11
  746. package/ref-monty/crates/monty/test_cases/loop__break_nested_except_clears.py +0 -55
  747. package/ref-monty/crates/monty/test_cases/loop__break_outside_error.py +0 -9
  748. package/ref-monty/crates/monty/test_cases/loop__continue_finally.py +0 -81
  749. package/ref-monty/crates/monty/test_cases/loop__continue_in_function_error.py +0 -13
  750. package/ref-monty/crates/monty/test_cases/loop__continue_in_if_error.py +0 -11
  751. package/ref-monty/crates/monty/test_cases/loop__continue_nested_except_clears.py +0 -60
  752. package/ref-monty/crates/monty/test_cases/loop__continue_outside_error.py +0 -9
  753. package/ref-monty/crates/monty/test_cases/math__acos_domain_error.py +0 -11
  754. package/ref-monty/crates/monty/test_cases/math__acosh_domain_error.py +0 -11
  755. package/ref-monty/crates/monty/test_cases/math__asin_domain_error.py +0 -11
  756. package/ref-monty/crates/monty/test_cases/math__atanh_domain_error.py +0 -11
  757. package/ref-monty/crates/monty/test_cases/math__cos_inf_error.py +0 -11
  758. package/ref-monty/crates/monty/test_cases/math__cosh_overflow_error.py +0 -11
  759. package/ref-monty/crates/monty/test_cases/math__exp_overflow_error.py +0 -11
  760. package/ref-monty/crates/monty/test_cases/math__factorial_float_error.py +0 -11
  761. package/ref-monty/crates/monty/test_cases/math__factorial_negative_error.py +0 -11
  762. package/ref-monty/crates/monty/test_cases/math__floor_inf_error.py +0 -11
  763. package/ref-monty/crates/monty/test_cases/math__floor_nan_error.py +0 -11
  764. package/ref-monty/crates/monty/test_cases/math__floor_str_error.py +0 -11
  765. package/ref-monty/crates/monty/test_cases/math__fmod_inf_error.py +0 -11
  766. package/ref-monty/crates/monty/test_cases/math__gamma_neg_int_error.py +0 -11
  767. package/ref-monty/crates/monty/test_cases/math__gcd_float_error.py +0 -11
  768. package/ref-monty/crates/monty/test_cases/math__isqrt_negative_error.py +0 -11
  769. package/ref-monty/crates/monty/test_cases/math__ldexp_overflow_error.py +0 -11
  770. package/ref-monty/crates/monty/test_cases/math__log1p_domain_error.py +0 -11
  771. package/ref-monty/crates/monty/test_cases/math__log_base1_error.py +0 -11
  772. package/ref-monty/crates/monty/test_cases/math__log_zero_error.py +0 -11
  773. package/ref-monty/crates/monty/test_cases/math__module.py +0 -1432
  774. package/ref-monty/crates/monty/test_cases/math__pow_domain_error.py +0 -11
  775. package/ref-monty/crates/monty/test_cases/math__sin_inf_error.py +0 -11
  776. package/ref-monty/crates/monty/test_cases/math__sqrt_negative_error.py +0 -11
  777. package/ref-monty/crates/monty/test_cases/math__tan_inf_error.py +0 -11
  778. package/ref-monty/crates/monty/test_cases/math__trunc_str_error.py +0 -11
  779. package/ref-monty/crates/monty/test_cases/method__args_kwargs_unpacking.py +0 -259
  780. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_func.py +0 -19
  781. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_module.py +0 -12
  782. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_chained.py +0 -9
  783. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_expr.py +0 -9
  784. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_function.py +0 -16
  785. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_with_args.py +0 -9
  786. package/ref-monty/crates/monty/test_cases/name_error__undefined_global.py +0 -10
  787. package/ref-monty/crates/monty/test_cases/namedtuple__missing_attr.py +0 -11
  788. package/ref-monty/crates/monty/test_cases/namedtuple__ops.py +0 -34
  789. package/ref-monty/crates/monty/test_cases/nonlocal__error_module_level.py +0 -3
  790. package/ref-monty/crates/monty/test_cases/nonlocal__ops.py +0 -353
  791. package/ref-monty/crates/monty/test_cases/os__environ.py +0 -40
  792. package/ref-monty/crates/monty/test_cases/os__getenv_key_list_error.py +0 -5
  793. package/ref-monty/crates/monty/test_cases/os__getenv_key_type_error.py +0 -5
  794. package/ref-monty/crates/monty/test_cases/parse_error__complex.py +0 -3
  795. package/ref-monty/crates/monty/test_cases/pathlib__import.py +0 -11
  796. package/ref-monty/crates/monty/test_cases/pathlib__os.py +0 -136
  797. package/ref-monty/crates/monty/test_cases/pathlib__os_read_error.py +0 -12
  798. package/ref-monty/crates/monty/test_cases/pathlib__pure.py +0 -81
  799. package/ref-monty/crates/monty/test_cases/pyobject__cycle_dict_self.py +0 -5
  800. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_dict.py +0 -6
  801. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_self.py +0 -5
  802. package/ref-monty/crates/monty/test_cases/pyobject__cycle_multiple_refs.py +0 -6
  803. package/ref-monty/crates/monty/test_cases/range__error_no_args.py +0 -2
  804. package/ref-monty/crates/monty/test_cases/range__error_step_zero.py +0 -2
  805. package/ref-monty/crates/monty/test_cases/range__error_too_many_args.py +0 -2
  806. package/ref-monty/crates/monty/test_cases/range__getitem_index_error.py +0 -10
  807. package/ref-monty/crates/monty/test_cases/range__ops.py +0 -236
  808. package/ref-monty/crates/monty/test_cases/re__basic.py +0 -756
  809. package/ref-monty/crates/monty/test_cases/re__grouping.py +0 -241
  810. package/ref-monty/crates/monty/test_cases/re__match.py +0 -148
  811. package/ref-monty/crates/monty/test_cases/recursion__deep_drop.py +0 -26
  812. package/ref-monty/crates/monty/test_cases/recursion__deep_eq.py +0 -23
  813. package/ref-monty/crates/monty/test_cases/recursion__deep_hash.py +0 -46
  814. package/ref-monty/crates/monty/test_cases/recursion__deep_repr.py +0 -12
  815. package/ref-monty/crates/monty/test_cases/recursion__function_depth.py +0 -13
  816. package/ref-monty/crates/monty/test_cases/refcount__cycle_mutual_reference.py +0 -18
  817. package/ref-monty/crates/monty/test_cases/refcount__cycle_self_reference.py +0 -12
  818. package/ref-monty/crates/monty/test_cases/refcount__dict_basic.py +0 -5
  819. package/ref-monty/crates/monty/test_cases/refcount__dict_get.py +0 -5
  820. package/ref-monty/crates/monty/test_cases/refcount__dict_keys_and.py +0 -14
  821. package/ref-monty/crates/monty/test_cases/refcount__dict_overwrite.py +0 -6
  822. package/ref-monty/crates/monty/test_cases/refcount__gather_cleanup.py +0 -16
  823. package/ref-monty/crates/monty/test_cases/refcount__gather_exception.py +0 -18
  824. package/ref-monty/crates/monty/test_cases/refcount__gather_nested_cancel.py +0 -25
  825. package/ref-monty/crates/monty/test_cases/refcount__immediate_skipped.py +0 -4
  826. package/ref-monty/crates/monty/test_cases/refcount__kwargs_unpacking.py +0 -27
  827. package/ref-monty/crates/monty/test_cases/refcount__list_append_multiple.py +0 -6
  828. package/ref-monty/crates/monty/test_cases/refcount__list_append_ref.py +0 -5
  829. package/ref-monty/crates/monty/test_cases/refcount__list_concat.py +0 -5
  830. package/ref-monty/crates/monty/test_cases/refcount__list_getitem.py +0 -5
  831. package/ref-monty/crates/monty/test_cases/refcount__list_iadd.py +0 -5
  832. package/ref-monty/crates/monty/test_cases/refcount__nested_list.py +0 -4
  833. package/ref-monty/crates/monty/test_cases/refcount__re_pattern_sub_error_paths.py +0 -37
  834. package/ref-monty/crates/monty/test_cases/refcount__re_search_match.py +0 -34
  835. package/ref-monty/crates/monty/test_cases/refcount__re_sub_error_paths.py +0 -31
  836. package/ref-monty/crates/monty/test_cases/refcount__shared_reference.py +0 -4
  837. package/ref-monty/crates/monty/test_cases/refcount__single_list.py +0 -3
  838. package/ref-monty/crates/monty/test_cases/repr__cycle_detection.py +0 -24
  839. package/ref-monty/crates/monty/test_cases/set__ops.py +0 -191
  840. package/ref-monty/crates/monty/test_cases/set__review_bugs.py +0 -35
  841. package/ref-monty/crates/monty/test_cases/set__unpack_type_error.py +0 -2
  842. package/ref-monty/crates/monty/test_cases/slice__invalid_indices.py +0 -2
  843. package/ref-monty/crates/monty/test_cases/slice__kwargs.py +0 -9
  844. package/ref-monty/crates/monty/test_cases/slice__no_args.py +0 -9
  845. package/ref-monty/crates/monty/test_cases/slice__ops.py +0 -149
  846. package/ref-monty/crates/monty/test_cases/slice__step_zero.py +0 -9
  847. package/ref-monty/crates/monty/test_cases/slice__step_zero_bytes.py +0 -9
  848. package/ref-monty/crates/monty/test_cases/slice__step_zero_range.py +0 -9
  849. package/ref-monty/crates/monty/test_cases/slice__step_zero_str.py +0 -9
  850. package/ref-monty/crates/monty/test_cases/slice__step_zero_tuple.py +0 -9
  851. package/ref-monty/crates/monty/test_cases/slice__too_many_args.py +0 -9
  852. package/ref-monty/crates/monty/test_cases/str__getitem_index_error.py +0 -10
  853. package/ref-monty/crates/monty/test_cases/str__index_not_found.py +0 -9
  854. package/ref-monty/crates/monty/test_cases/str__join_no_args.py +0 -9
  855. package/ref-monty/crates/monty/test_cases/str__join_non_string.py +0 -9
  856. package/ref-monty/crates/monty/test_cases/str__join_not_iterable.py +0 -9
  857. package/ref-monty/crates/monty/test_cases/str__join_too_many_args.py +0 -9
  858. package/ref-monty/crates/monty/test_cases/str__methods.py +0 -327
  859. package/ref-monty/crates/monty/test_cases/str__ops.py +0 -162
  860. package/ref-monty/crates/monty/test_cases/str__partition_empty.py +0 -9
  861. package/ref-monty/crates/monty/test_cases/str__rsplit_empty_sep.py +0 -9
  862. package/ref-monty/crates/monty/test_cases/str__split_empty_sep.py +0 -9
  863. package/ref-monty/crates/monty/test_cases/sys__types.py +0 -7
  864. package/ref-monty/crates/monty/test_cases/traceback__division_error.py +0 -30
  865. package/ref-monty/crates/monty/test_cases/traceback__index_error.py +0 -17
  866. package/ref-monty/crates/monty/test_cases/traceback__insert_as_int.py +0 -10
  867. package/ref-monty/crates/monty/test_cases/traceback__nested_call.py +0 -29
  868. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_module_scope.py +0 -10
  869. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_unbound.py +0 -24
  870. package/ref-monty/crates/monty/test_cases/traceback__range_as_int.py +0 -9
  871. package/ref-monty/crates/monty/test_cases/traceback__recursion_error.py +0 -23
  872. package/ref-monty/crates/monty/test_cases/traceback__set_mutation.py +0 -11
  873. package/ref-monty/crates/monty/test_cases/traceback__undefined_attr_call.py +0 -16
  874. package/ref-monty/crates/monty/test_cases/traceback__undefined_call.py +0 -16
  875. package/ref-monty/crates/monty/test_cases/traceback__undefined_raise.py +0 -16
  876. package/ref-monty/crates/monty/test_cases/try_except__all.py +0 -472
  877. package/ref-monty/crates/monty/test_cases/try_except__bare_raise_no_context.py +0 -2
  878. package/ref-monty/crates/monty/test_cases/try_except__invalid_type.py +0 -5
  879. package/ref-monty/crates/monty/test_cases/tuple__getitem_out_of_bounds.py +0 -3
  880. package/ref-monty/crates/monty/test_cases/tuple__index_not_found.py +0 -9
  881. package/ref-monty/crates/monty/test_cases/tuple__index_start_gt_end.py +0 -10
  882. package/ref-monty/crates/monty/test_cases/tuple__methods.py +0 -19
  883. package/ref-monty/crates/monty/test_cases/tuple__ops.py +0 -133
  884. package/ref-monty/crates/monty/test_cases/tuple__unpack_type_error.py +0 -2
  885. package/ref-monty/crates/monty/test_cases/type__builtin_attr_error.py +0 -9
  886. package/ref-monty/crates/monty/test_cases/type__bytes_negative.py +0 -2
  887. package/ref-monty/crates/monty/test_cases/type__cell_not_builtin.py +0 -9
  888. package/ref-monty/crates/monty/test_cases/type__exception_attr_error.py +0 -11
  889. package/ref-monty/crates/monty/test_cases/type__float_conversion_error.py +0 -2
  890. package/ref-monty/crates/monty/test_cases/type__float_repr_both_quotes.py +0 -9
  891. package/ref-monty/crates/monty/test_cases/type__float_repr_newline.py +0 -9
  892. package/ref-monty/crates/monty/test_cases/type__float_repr_single_quote.py +0 -9
  893. package/ref-monty/crates/monty/test_cases/type__int_conversion_error.py +0 -2
  894. package/ref-monty/crates/monty/test_cases/type__list_not_iterable.py +0 -2
  895. package/ref-monty/crates/monty/test_cases/type__non_builtin_name_error.py +0 -9
  896. package/ref-monty/crates/monty/test_cases/type__ops.py +0 -200
  897. package/ref-monty/crates/monty/test_cases/type__shadow_exc.py +0 -3
  898. package/ref-monty/crates/monty/test_cases/type__shadow_int.py +0 -9
  899. package/ref-monty/crates/monty/test_cases/type__shadow_len.py +0 -3
  900. package/ref-monty/crates/monty/test_cases/type__tuple_not_iterable.py +0 -2
  901. package/ref-monty/crates/monty/test_cases/type_error__int_add_list.py +0 -2
  902. package/ref-monty/crates/monty/test_cases/type_error__int_div_str.py +0 -2
  903. package/ref-monty/crates/monty/test_cases/type_error__int_floordiv_str.py +0 -2
  904. package/ref-monty/crates/monty/test_cases/type_error__int_iadd_str.py +0 -3
  905. package/ref-monty/crates/monty/test_cases/type_error__int_mod_str.py +0 -2
  906. package/ref-monty/crates/monty/test_cases/type_error__int_pow_str.py +0 -2
  907. package/ref-monty/crates/monty/test_cases/type_error__int_sub_str.py +0 -2
  908. package/ref-monty/crates/monty/test_cases/type_error__list_add_int.py +0 -2
  909. package/ref-monty/crates/monty/test_cases/type_error__list_add_str.py +0 -2
  910. package/ref-monty/crates/monty/test_cases/type_error__list_iadd_int.py +0 -6
  911. package/ref-monty/crates/monty/test_cases/type_error__str_add_int.py +0 -2
  912. package/ref-monty/crates/monty/test_cases/type_error__str_iadd_int.py +0 -3
  913. package/ref-monty/crates/monty/test_cases/type_error__unary_invert_str.py +0 -3
  914. package/ref-monty/crates/monty/test_cases/type_error__unary_minus_str.py +0 -4
  915. package/ref-monty/crates/monty/test_cases/type_error__unary_neg_str.py +0 -3
  916. package/ref-monty/crates/monty/test_cases/type_error__unary_plus_str.py +0 -4
  917. package/ref-monty/crates/monty/test_cases/typing__types.py +0 -24
  918. package/ref-monty/crates/monty/test_cases/unpack__nested.py +0 -48
  919. package/ref-monty/crates/monty/test_cases/unpack__non_sequence.py +0 -9
  920. package/ref-monty/crates/monty/test_cases/unpack__not_enough.py +0 -9
  921. package/ref-monty/crates/monty/test_cases/unpack__ops.py +0 -153
  922. package/ref-monty/crates/monty/test_cases/unpack__star_not_enough.py +0 -9
  923. package/ref-monty/crates/monty/test_cases/unpack__too_many.py +0 -9
  924. package/ref-monty/crates/monty/test_cases/version__cpython.py +0 -4
  925. package/ref-monty/crates/monty/test_cases/walrus__all.py +0 -178
  926. package/ref-monty/crates/monty/test_cases/while__all.py +0 -206
  927. package/ref-monty/crates/monty/tests/asyncio.rs +0 -764
  928. package/ref-monty/crates/monty/tests/binary_serde.rs +0 -185
  929. package/ref-monty/crates/monty/tests/bytecode_limits.rs +0 -248
  930. package/ref-monty/crates/monty/tests/datatest_runner.rs +0 -2029
  931. package/ref-monty/crates/monty/tests/inputs.rs +0 -420
  932. package/ref-monty/crates/monty/tests/json_serde.rs +0 -250
  933. package/ref-monty/crates/monty/tests/main.rs +0 -71
  934. package/ref-monty/crates/monty/tests/math_module.rs +0 -114
  935. package/ref-monty/crates/monty/tests/name_lookup.rs +0 -482
  936. package/ref-monty/crates/monty/tests/os_tests.rs +0 -459
  937. package/ref-monty/crates/monty/tests/parse_errors.rs +0 -441
  938. package/ref-monty/crates/monty/tests/print_writer.rs +0 -238
  939. package/ref-monty/crates/monty/tests/py_object.rs +0 -121
  940. package/ref-monty/crates/monty/tests/regex.rs +0 -90
  941. package/ref-monty/crates/monty/tests/repl.rs +0 -344
  942. package/ref-monty/crates/monty/tests/resource_limits.rs +0 -1826
  943. package/ref-monty/crates/monty/tests/try_from.rs +0 -167
  944. package/ref-monty/crates/monty-cli/Cargo.toml +0 -25
  945. package/ref-monty/crates/monty-cli/src/main.rs +0 -541
  946. package/ref-monty/crates/monty-js/.cargo/config.toml +0 -2
  947. package/ref-monty/crates/monty-js/.prettierignore +0 -8
  948. package/ref-monty/crates/monty-js/Cargo.toml +0 -32
  949. package/ref-monty/crates/monty-js/README.md +0 -207
  950. package/ref-monty/crates/monty-js/__test__/async.spec.ts +0 -350
  951. package/ref-monty/crates/monty-js/__test__/basic.spec.ts +0 -114
  952. package/ref-monty/crates/monty-js/__test__/exceptions.spec.ts +0 -427
  953. package/ref-monty/crates/monty-js/__test__/external.spec.ts +0 -354
  954. package/ref-monty/crates/monty-js/__test__/inputs.spec.ts +0 -143
  955. package/ref-monty/crates/monty-js/__test__/limits.spec.ts +0 -162
  956. package/ref-monty/crates/monty-js/__test__/package.json +0 -3
  957. package/ref-monty/crates/monty-js/__test__/print.spec.ts +0 -229
  958. package/ref-monty/crates/monty-js/__test__/repl.spec.ts +0 -34
  959. package/ref-monty/crates/monty-js/__test__/serialize.spec.ts +0 -205
  960. package/ref-monty/crates/monty-js/__test__/start.spec.ts +0 -443
  961. package/ref-monty/crates/monty-js/__test__/type_check.spec.ts +0 -147
  962. package/ref-monty/crates/monty-js/__test__/types.spec.ts +0 -319
  963. package/ref-monty/crates/monty-js/build.rs +0 -61
  964. package/ref-monty/crates/monty-js/index-header.d.ts +0 -3
  965. package/ref-monty/crates/monty-js/package-lock.json +0 -4694
  966. package/ref-monty/crates/monty-js/package.json +0 -100
  967. package/ref-monty/crates/monty-js/scripts/smoke-test.sh +0 -69
  968. package/ref-monty/crates/monty-js/smoke-test/package.json +0 -17
  969. package/ref-monty/crates/monty-js/smoke-test/test.ts +0 -171
  970. package/ref-monty/crates/monty-js/smoke-test/tsconfig.json +0 -11
  971. package/ref-monty/crates/monty-js/src/convert.rs +0 -648
  972. package/ref-monty/crates/monty-js/src/exceptions.rs +0 -293
  973. package/ref-monty/crates/monty-js/src/lib.rs +0 -41
  974. package/ref-monty/crates/monty-js/src/limits.rs +0 -53
  975. package/ref-monty/crates/monty-js/src/monty_cls.rs +0 -1407
  976. package/ref-monty/crates/monty-js/tsconfig.json +0 -17
  977. package/ref-monty/crates/monty-js/wrapper.ts +0 -701
  978. package/ref-monty/crates/monty-python/Cargo.toml +0 -38
  979. package/ref-monty/crates/monty-python/README.md +0 -134
  980. package/ref-monty/crates/monty-python/build.rs +0 -4
  981. package/ref-monty/crates/monty-python/example.py +0 -40
  982. package/ref-monty/crates/monty-python/exercise.py +0 -46
  983. package/ref-monty/crates/monty-python/pyproject.toml +0 -57
  984. package/ref-monty/crates/monty-python/python/pydantic_monty/__init__.py +0 -281
  985. package/ref-monty/crates/monty-python/python/pydantic_monty/_monty.pyi +0 -677
  986. package/ref-monty/crates/monty-python/python/pydantic_monty/os_access.py +0 -933
  987. package/ref-monty/crates/monty-python/python/pydantic_monty/py.typed +0 -0
  988. package/ref-monty/crates/monty-python/src/convert.rs +0 -273
  989. package/ref-monty/crates/monty-python/src/dataclass.rs +0 -461
  990. package/ref-monty/crates/monty-python/src/exceptions.rs +0 -557
  991. package/ref-monty/crates/monty-python/src/external.rs +0 -165
  992. package/ref-monty/crates/monty-python/src/lib.rs +0 -77
  993. package/ref-monty/crates/monty-python/src/limits.rs +0 -142
  994. package/ref-monty/crates/monty-python/src/monty_cls.rs +0 -1650
  995. package/ref-monty/crates/monty-python/src/repl.rs +0 -470
  996. package/ref-monty/crates/monty-python/src/serialization.rs +0 -761
  997. package/ref-monty/crates/monty-python/tests/test_async.py +0 -1201
  998. package/ref-monty/crates/monty-python/tests/test_basic.py +0 -66
  999. package/ref-monty/crates/monty-python/tests/test_dataclasses.py +0 -971
  1000. package/ref-monty/crates/monty-python/tests/test_exceptions.py +0 -361
  1001. package/ref-monty/crates/monty-python/tests/test_external.py +0 -367
  1002. package/ref-monty/crates/monty-python/tests/test_inputs.py +0 -126
  1003. package/ref-monty/crates/monty-python/tests/test_limits.py +0 -257
  1004. package/ref-monty/crates/monty-python/tests/test_os_access.py +0 -1286
  1005. package/ref-monty/crates/monty-python/tests/test_os_access_compat.py +0 -731
  1006. package/ref-monty/crates/monty-python/tests/test_os_access_raw.py +0 -483
  1007. package/ref-monty/crates/monty-python/tests/test_os_calls.py +0 -819
  1008. package/ref-monty/crates/monty-python/tests/test_print.py +0 -208
  1009. package/ref-monty/crates/monty-python/tests/test_re.py +0 -170
  1010. package/ref-monty/crates/monty-python/tests/test_readme_examples.py +0 -20
  1011. package/ref-monty/crates/monty-python/tests/test_repl.py +0 -749
  1012. package/ref-monty/crates/monty-python/tests/test_serialize.py +0 -284
  1013. package/ref-monty/crates/monty-python/tests/test_start.py +0 -346
  1014. package/ref-monty/crates/monty-python/tests/test_threading.py +0 -163
  1015. package/ref-monty/crates/monty-python/tests/test_type_check.py +0 -344
  1016. package/ref-monty/crates/monty-python/tests/test_types.py +0 -553
  1017. package/ref-monty/crates/monty-type-checking/Cargo.toml +0 -32
  1018. package/ref-monty/crates/monty-type-checking/src/db.rs +0 -116
  1019. package/ref-monty/crates/monty-type-checking/src/lib.rs +0 -4
  1020. package/ref-monty/crates/monty-type-checking/src/type_check.rs +0 -280
  1021. package/ref-monty/crates/monty-type-checking/tests/bad_types.py +0 -109
  1022. package/ref-monty/crates/monty-type-checking/tests/bad_types_output.txt +0 -21
  1023. package/ref-monty/crates/monty-type-checking/tests/good_types.py +0 -475
  1024. package/ref-monty/crates/monty-type-checking/tests/main.rs +0 -205
  1025. package/ref-monty/crates/monty-type-checking/tests/reveal_types.py +0 -56
  1026. package/ref-monty/crates/monty-type-checking/tests/reveal_types_output.txt +0 -41
  1027. package/ref-monty/crates/monty-typeshed/Cargo.toml +0 -29
  1028. package/ref-monty/crates/monty-typeshed/README.md +0 -11
  1029. package/ref-monty/crates/monty-typeshed/build.rs +0 -101
  1030. package/ref-monty/crates/monty-typeshed/custom/README.md +0 -1
  1031. package/ref-monty/crates/monty-typeshed/custom/asyncio.pyi +0 -138
  1032. package/ref-monty/crates/monty-typeshed/custom/os.pyi +0 -87
  1033. package/ref-monty/crates/monty-typeshed/custom/sys.pyi +0 -33
  1034. package/ref-monty/crates/monty-typeshed/src/lib.rs +0 -56
  1035. package/ref-monty/crates/monty-typeshed/update.py +0 -321
  1036. package/ref-monty/crates/monty-typeshed/vendor/typeshed/source_commit.txt +0 -1
  1037. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/VERSIONS +0 -20
  1038. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi +0 -105
  1039. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi +0 -394
  1040. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi +0 -138
  1041. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi +0 -1434
  1042. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi +0 -527
  1043. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/abc.pyi +0 -2
  1044. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/dataclasses.pyi +0 -502
  1045. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/enum.pyi +0 -376
  1046. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/math.pyi +0 -149
  1047. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/os.pyi +0 -87
  1048. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/__init__.pyi +0 -395
  1049. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/types.pyi +0 -8
  1050. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/re.pyi +0 -337
  1051. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/sys.pyi +0 -33
  1052. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/types.pyi +0 -741
  1053. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing.pyi +0 -1217
  1054. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing_extensions.pyi +0 -716
  1055. package/ref-monty/docs/usage-guide.md +0 -117
  1056. package/ref-monty/examples/README.md +0 -3
  1057. package/ref-monty/examples/expense_analysis/README.md +0 -3
  1058. package/ref-monty/examples/expense_analysis/data.py +0 -124
  1059. package/ref-monty/examples/expense_analysis/main.py +0 -115
  1060. package/ref-monty/examples/sql_playground/README.md +0 -20
  1061. package/ref-monty/examples/sql_playground/external_functions.py +0 -129
  1062. package/ref-monty/examples/sql_playground/main.py +0 -81
  1063. package/ref-monty/examples/sql_playground/sandbox_code.py +0 -82
  1064. package/ref-monty/examples/sql_playground/type_stubs.pyi +0 -14
  1065. package/ref-monty/examples/web_scraper/README.md +0 -15
  1066. package/ref-monty/examples/web_scraper/browser.py +0 -56
  1067. package/ref-monty/examples/web_scraper/example_code.py +0 -59
  1068. package/ref-monty/examples/web_scraper/external_functions.py +0 -324
  1069. package/ref-monty/examples/web_scraper/main.py +0 -193
  1070. package/ref-monty/examples/web_scraper/sub_agent.py +0 -79
  1071. package/ref-monty/monty-npm.md +0 -235
  1072. package/ref-monty/pyproject.toml +0 -162
  1073. package/ref-monty/scripts/check_imports.py +0 -91
  1074. package/ref-monty/scripts/codecov_diff.py +0 -412
  1075. package/ref-monty/scripts/complete_tests.py +0 -146
  1076. package/ref-monty/scripts/flamegraph_to_text.py +0 -208
  1077. package/ref-monty/scripts/iter_test_methods.py +0 -540
  1078. package/ref-monty/scripts/run_traceback.py +0 -180
  1079. package/ref-monty/scripts/startup_performance.py +0 -130
  1080. package/ref-monty/uv.lock +0 -1779
  1081. /package/docs/{plugin-examples.md → plugins-examples.md} +0 -0
@@ -1,1650 +0,0 @@
1
- use std::{
2
- borrow::Cow,
3
- fmt::Write,
4
- sync::{Mutex, PoisonError},
5
- };
6
-
7
- // Use `::monty` to refer to the external crate (not the pymodule)
8
- use ::monty::{
9
- ExtFunctionResult, FunctionCall, LimitedTracker, MontyException, MontyObject, MontyRun, NameLookupResult,
10
- NoLimitTracker, OsCall, PrintWriter, PrintWriterCallback, ReplFunctionCall, ReplNameLookup, ReplOsCall,
11
- ReplProgress, ReplResolveFutures, ReplStartError, ResolveFutures, ResourceTracker, RunProgress,
12
- };
13
- use monty::{ExcType, NameLookup};
14
- use monty_type_checking::{SourceFile, type_check};
15
- use pyo3::{
16
- IntoPyObjectExt,
17
- exceptions::{PyKeyError, PyRuntimeError, PyTypeError, PyValueError},
18
- intern,
19
- prelude::*,
20
- types::{PyBytes, PyDict, PyList, PyTuple, PyType},
21
- };
22
- use send_wrapper::SendWrapper;
23
-
24
- use crate::{
25
- convert::{get_docstring, monty_to_py, py_to_monty},
26
- dataclass::DcRegistry,
27
- exceptions::{MontyError, MontyTypingError, exc_py_to_monty},
28
- external::{ExternalFunctionRegistry, dispatch_method_call},
29
- limits::{PySignalTracker, extract_limits},
30
- repl::{EitherRepl, FromCoreRepl, PyMontyRepl},
31
- };
32
-
33
- /// A sandboxed Python interpreter instance.
34
- ///
35
- /// Parses and compiles Python code on initialization, then can be run
36
- /// multiple times with different input values. This separates the parsing
37
- /// cost from execution, making repeated runs more efficient.
38
- #[pyclass(name = "Monty", module = "pydantic_monty")]
39
- #[derive(Debug)]
40
- pub struct PyMonty {
41
- /// The compiled code snapshot, ready to execute.
42
- runner: MontyRun,
43
- /// The artificial name of the python code "file"
44
- script_name: String,
45
- /// Names of input variables expected by the code.
46
- input_names: Vec<String>,
47
- /// Registry of dataclass types for reconstructing original types on output.
48
- ///
49
- /// Maps type pointer identity (`u64`) to the original Python type, allowing
50
- /// `isinstance(result, OriginalClass)` to work correctly after round-tripping through Monty.
51
- dc_registry: DcRegistry,
52
- }
53
-
54
- #[pymethods]
55
- impl PyMonty {
56
- /// Creates a new Monty interpreter by parsing the given code.
57
- ///
58
- /// # Arguments
59
- /// * `code` - Python code to execute
60
- /// * `inputs` - List of input variable names available in the code
61
- /// * `type_check` - Whether to perform type checking on the code
62
- /// * `type_check_stubs` - Prefix code to be executed before type checking
63
- /// * `dataclass_registry` - Registry of dataclass types for reconstructing original types on output.
64
- #[new]
65
- #[pyo3(signature = (code, *, script_name="main.py", inputs=None, type_check=false, type_check_stubs=None, dataclass_registry=None))]
66
- fn new(
67
- py: Python<'_>,
68
- code: String,
69
- script_name: &str,
70
- inputs: Option<&Bound<'_, PyList>>,
71
- type_check: bool,
72
- type_check_stubs: Option<&str>,
73
- dataclass_registry: Option<&Bound<'_, PyList>>,
74
- ) -> PyResult<Self> {
75
- let input_names = list_str(inputs, "inputs")?;
76
-
77
- if type_check {
78
- py_type_check(py, &code, script_name, type_check_stubs)?;
79
- }
80
-
81
- // Create the snapshot (parses the code)
82
- let runner = MontyRun::new(code, script_name, input_names.clone()).map_err(|e| MontyError::new_err(py, e))?;
83
-
84
- Ok(Self {
85
- runner,
86
- script_name: script_name.to_string(),
87
- input_names,
88
- dc_registry: DcRegistry::from_list(py, dataclass_registry)?,
89
- })
90
- }
91
-
92
- /// Registers a dataclass type for proper isinstance() support on output.
93
- ///
94
- /// When a dataclass passes through Monty and is returned, it becomes a `MontyDataclass`.
95
- /// By registering the original type, `isinstance(result, OriginalClass)` will return `True`.
96
- ///
97
- /// # Arguments
98
- /// * `cls` - The dataclass type to register
99
- ///
100
- /// # Raises
101
- /// * `TypeError` if the argument is not a dataclass type
102
- fn register_dataclass(&self, cls: &Bound<'_, PyType>) -> PyResult<()> {
103
- self.dc_registry.insert(cls)
104
- }
105
-
106
- /// Performs static type checking on the code.
107
- ///
108
- /// Analyzes the code for type errors without executing it. This uses
109
- /// a subset of Python's type system supported by Monty.
110
- ///
111
- /// # Args
112
- /// * `prefix_code` - Optional prefix to prepend to the code before type checking,
113
- /// e.g. with inputs and external function signatures
114
- ///
115
- /// # Raises
116
- /// * `RuntimeError` if type checking infrastructure fails
117
- /// * `MontyTypingError` if type errors are found
118
- #[pyo3(signature = (prefix_code=None))]
119
- fn type_check(&self, py: Python<'_>, prefix_code: Option<&str>) -> PyResult<()> {
120
- py_type_check(py, self.runner.code(), &self.script_name, prefix_code)
121
- }
122
-
123
- /// Executes the code and returns the result.
124
- ///
125
- /// # Returns
126
- /// The result of the last expression in the code
127
- ///
128
- /// # Raises
129
- /// Various Python exceptions matching what the code would raise
130
- #[pyo3(signature = (*, inputs=None, limits=None, external_functions=None, print_callback=None, os=None))]
131
- fn run(
132
- &self,
133
- py: Python<'_>,
134
- inputs: Option<&Bound<'_, PyDict>>,
135
- limits: Option<&Bound<'_, PyDict>>,
136
- external_functions: Option<&Bound<'_, PyDict>>,
137
- print_callback: Option<&Bound<'_, PyAny>>,
138
- os: Option<&Bound<'_, PyAny>>,
139
- ) -> PyResult<Py<PyAny>> {
140
- // Clone the Arc handle — all clones share the same underlying registry,
141
- // so auto-registrations during execution are visible to all users.
142
- let input_values = self.extract_input_values(inputs, &self.dc_registry)?;
143
-
144
- if let Some(os_callback) = os
145
- && !os_callback.is_callable()
146
- {
147
- let msg = format!("TypeError: '{}' object is not callable", os_callback.get_type().name()?);
148
- return Err(PyTypeError::new_err(msg));
149
- }
150
-
151
- // Build print writer
152
- let mut print_cb;
153
- let print_writer = match print_callback {
154
- Some(cb) => {
155
- print_cb = CallbackStringPrint::new(cb);
156
- PrintWriter::Callback(&mut print_cb)
157
- }
158
- None => PrintWriter::Stdout,
159
- };
160
-
161
- // Run with appropriate tracker type (must branch due to different generic types)
162
- if let Some(limits) = limits {
163
- let tracker = PySignalTracker::new(LimitedTracker::new(extract_limits(limits)?));
164
- self.run_impl(py, input_values, tracker, external_functions, os, print_writer)
165
- } else {
166
- let tracker = PySignalTracker::new(NoLimitTracker);
167
- self.run_impl(py, input_values, tracker, external_functions, os, print_writer)
168
- }
169
- }
170
-
171
- #[pyo3(signature = (*, inputs=None, limits=None, print_callback=None))]
172
- fn start<'py>(
173
- &self,
174
- py: Python<'py>,
175
- inputs: Option<&Bound<'py, PyDict>>,
176
- limits: Option<&Bound<'py, PyDict>>,
177
- print_callback: Option<Bound<'_, PyAny>>,
178
- ) -> PyResult<Bound<'py, PyAny>> {
179
- // Clone the Arc handle — shares the same underlying registry
180
- let dc_registry = self.dc_registry.clone_ref(py);
181
- let input_values = self.extract_input_values(inputs, &dc_registry)?;
182
-
183
- // Build print writer - CallbackStringPrint is Send so GIL can be released
184
- let mut print_cb;
185
- let print_writer = match &print_callback {
186
- Some(cb) => {
187
- print_cb = CallbackStringPrint::new(cb);
188
- PrintWriter::Callback(&mut print_cb)
189
- }
190
- None => PrintWriter::Stdout,
191
- };
192
-
193
- let runner = self.runner.clone();
194
- let print_writer = SendWrapper::new(print_writer);
195
-
196
- // Helper macro to start execution with GIL released
197
- macro_rules! start_impl {
198
- ($tracker:expr) => {{
199
- py.detach(|| runner.start(input_values, $tracker, print_writer.take()))
200
- .map_err(|e| MontyError::new_err(py, e))?
201
- }};
202
- }
203
-
204
- // Branch on limits (different generic types)
205
- let progress = if let Some(limits) = limits {
206
- let tracker = PySignalTracker::new(LimitedTracker::new(extract_limits(limits)?));
207
- EitherProgress::Limited(start_impl!(tracker))
208
- } else {
209
- let tracker = PySignalTracker::new(NoLimitTracker);
210
- EitherProgress::NoLimit(start_impl!(tracker))
211
- };
212
- progress.progress_or_complete(
213
- py,
214
- self.script_name.clone(),
215
- print_callback.map(Bound::unbind),
216
- dc_registry,
217
- )
218
- }
219
-
220
- /// Serializes the Monty instance to a binary format.
221
- ///
222
- /// The serialized data can be stored and later restored with `Monty.load()`.
223
- /// This allows caching parsed code to avoid re-parsing on subsequent runs.
224
- ///
225
- /// # Returns
226
- /// Bytes containing the serialized Monty instance.
227
- ///
228
- /// # Raises
229
- /// `ValueError` if serialization fails.
230
- fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
231
- let serialized = SerializedMonty {
232
- runner: self.runner.clone(),
233
- script_name: self.script_name.clone(),
234
- input_names: self.input_names.clone(),
235
- };
236
- let bytes = postcard::to_allocvec(&serialized).map_err(|e| PyValueError::new_err(e.to_string()))?;
237
- Ok(PyBytes::new(py, &bytes))
238
- }
239
-
240
- /// Deserializes a Monty instance from binary format.
241
- ///
242
- /// # Arguments
243
- /// * `data` - The serialized Monty data from `dump()`
244
- /// * `dataclass_registry` - Optional list of dataclasses to register
245
- ///
246
- /// # Returns
247
- /// A new Monty instance.
248
- ///
249
- /// # Raises
250
- /// `ValueError` if deserialization fails.
251
- #[staticmethod]
252
- #[pyo3(signature = (data, *, dataclass_registry=None))]
253
- fn load(
254
- py: Python<'_>,
255
- data: &Bound<'_, PyBytes>,
256
- dataclass_registry: Option<&Bound<'_, PyList>>,
257
- ) -> PyResult<Self> {
258
- let bytes = data.as_bytes();
259
- let serialized: SerializedMonty =
260
- postcard::from_bytes(bytes).map_err(|e| PyValueError::new_err(e.to_string()))?;
261
-
262
- Ok(Self {
263
- runner: serialized.runner,
264
- script_name: serialized.script_name,
265
- input_names: serialized.input_names,
266
- dc_registry: DcRegistry::from_list(py, dataclass_registry)?,
267
- })
268
- }
269
-
270
- fn __repr__(&self) -> String {
271
- let lines = self.runner.code().lines().count();
272
- let mut s = format!(
273
- "Monty(<{} line{} of code>, script_name='{}'",
274
- lines,
275
- if lines == 1 { "" } else { "s" },
276
- self.script_name
277
- );
278
- if !self.input_names.is_empty() {
279
- write!(s, ", inputs={:?}", self.input_names).unwrap();
280
- }
281
- s.push(')');
282
- s
283
- }
284
- }
285
-
286
- fn py_type_check(py: Python<'_>, code: &str, script_name: &str, type_stubs: Option<&str>) -> PyResult<()> {
287
- let type_stubs = type_stubs.map(|type_stubs| SourceFile::new(type_stubs, "type_stubs.pyi"));
288
-
289
- let opt_diagnostics =
290
- type_check(&SourceFile::new(code, script_name), type_stubs.as_ref()).map_err(PyRuntimeError::new_err)?;
291
-
292
- if let Some(diagnostic) = opt_diagnostics {
293
- Err(MontyTypingError::new_err(py, diagnostic))
294
- } else {
295
- Ok(())
296
- }
297
- }
298
-
299
- impl PyMonty {
300
- /// Extracts input values from a Python dict in the order they were declared.
301
- ///
302
- /// Validates that all required inputs are provided. Any dataclass inputs are
303
- /// automatically registered in `dc_registry` via `py_to_monty` so they can be
304
- /// properly reconstructed on output.
305
- fn extract_input_values(
306
- &self,
307
- inputs: Option<&Bound<'_, PyDict>>,
308
- dc_registry: &DcRegistry,
309
- ) -> PyResult<Vec<::monty::MontyObject>> {
310
- if self.input_names.is_empty() {
311
- if inputs.is_some() {
312
- return Err(PyTypeError::new_err(
313
- "No input variables declared but inputs dict was provided",
314
- ));
315
- }
316
- return Ok(vec![]);
317
- }
318
-
319
- let Some(inputs) = inputs else {
320
- return Err(PyTypeError::new_err(format!(
321
- "Missing required inputs: {:?}",
322
- self.input_names
323
- )));
324
- };
325
-
326
- // Extract values in declaration order
327
- self.input_names
328
- .iter()
329
- .map(|name| {
330
- let value = inputs
331
- .get_item(name)?
332
- .ok_or_else(|| PyKeyError::new_err(format!("Missing required input: '{name}'")))?;
333
- py_to_monty(&value, dc_registry)
334
- })
335
- .collect::<PyResult<_>>()
336
- }
337
-
338
- /// Runs code with a generic resource tracker, releasing the GIL during execution.
339
- ///
340
- /// Takes explicit field references instead of `&mut self` so that `run()` can
341
- /// remain `&self` (required for concurrent thread access in PyO3).
342
- fn run_impl(
343
- &self,
344
- py: Python<'_>,
345
- input_values: Vec<MontyObject>,
346
- tracker: impl ResourceTracker + Send,
347
- external_functions: Option<&Bound<'_, PyDict>>,
348
- os: Option<&Bound<'_, PyAny>>,
349
- print_output: PrintWriter<'_>,
350
- ) -> PyResult<Py<PyAny>> {
351
- // wrap print_output in SendWrapper so that it can be accessed inside the py.detach calls despite
352
- // no `Send` bound - py.detach() is overly restrictive to prevent `Bound` types going inside
353
- let mut print_output = SendWrapper::new(print_output);
354
-
355
- // Check if any inputs contain dataclasses (including nested in containers) —
356
- // if so, we need the iterative path because method calls could happen lazily
357
- // and need to be dispatched to the host.
358
- let has_dataclass_inputs = || input_values.iter().any(contains_dataclass);
359
-
360
- if external_functions.is_none() && os.is_none() && !has_dataclass_inputs() {
361
- return match py.detach(|| self.runner.run(input_values, tracker, print_output.reborrow())) {
362
- Ok(v) => monty_to_py(py, &v, &self.dc_registry),
363
- Err(err) => Err(MontyError::new_err(py, err)),
364
- };
365
- }
366
- // Clone the runner since start() consumes it - allows reuse of the parsed code
367
- let runner = self.runner.clone();
368
- let mut progress = py
369
- .detach(|| runner.start(input_values, tracker, print_output.reborrow()))
370
- .map_err(|e| MontyError::new_err(py, e))?;
371
-
372
- loop {
373
- match progress {
374
- RunProgress::Complete(result) => return monty_to_py(py, &result, &self.dc_registry),
375
- RunProgress::FunctionCall(call) => {
376
- // Dataclass method calls have method_call=true and the first arg is the instance
377
- let return_value = if call.method_call {
378
- dispatch_method_call(py, &call.function_name, &call.args, &call.kwargs, &self.dc_registry)
379
- } else if let Some(ext_fns) = external_functions {
380
- let registry = ExternalFunctionRegistry::new(py, ext_fns, &self.dc_registry);
381
- registry.call(&call.function_name, &call.args, &call.kwargs)
382
- } else {
383
- return Err(PyRuntimeError::new_err(format!(
384
- "External function '{}' called but no external_functions provided",
385
- call.function_name
386
- )));
387
- };
388
-
389
- progress = py
390
- .detach(|| call.resume(return_value, print_output.reborrow()))
391
- .map_err(|e| MontyError::new_err(py, e))?;
392
- }
393
- RunProgress::NameLookup(lookup) => {
394
- let result = if let Some(ext_fns) = external_functions
395
- && let Some(value) = ext_fns.get_item(&lookup.name)?
396
- {
397
- NameLookupResult::Value(MontyObject::Function {
398
- name: lookup.name.clone(),
399
- docstring: get_docstring(&value),
400
- })
401
- } else {
402
- NameLookupResult::Undefined
403
- };
404
-
405
- progress = py
406
- .detach(|| lookup.resume(result, print_output.reborrow()))
407
- .map_err(|e| MontyError::new_err(py, e))?;
408
- }
409
- RunProgress::ResolveFutures(_) => {
410
- return Err(PyRuntimeError::new_err("async futures not supported with `Monty.run`"));
411
- }
412
- RunProgress::OsCall(call) => {
413
- let result: ExtFunctionResult = if let Some(os_callback) = os {
414
- // Convert args to Python
415
- let py_args: Vec<Py<PyAny>> = call
416
- .args
417
- .iter()
418
- .map(|arg| monty_to_py(py, arg, &self.dc_registry))
419
- .collect::<PyResult<_>>()?;
420
- let py_args_tuple = PyTuple::new(py, py_args)?;
421
-
422
- // Convert kwargs to Python dict
423
- let py_kwargs = PyDict::new(py);
424
- for (k, v) in &call.kwargs {
425
- py_kwargs.set_item(
426
- monty_to_py(py, k, &self.dc_registry)?,
427
- monty_to_py(py, v, &self.dc_registry)?,
428
- )?;
429
- }
430
-
431
- // call the os callback, if an exception is raised, return it to monty
432
- match os_callback.call1((call.function.to_string(), py_args_tuple, py_kwargs)) {
433
- Ok(result) => py_to_monty(&result, &self.dc_registry)?.into(),
434
- Err(err) => exc_py_to_monty(py, &err).into(),
435
- }
436
- } else {
437
- MontyException::new(
438
- ExcType::NotImplementedError,
439
- Some(format!("OS function '{}' not implemented", call.function)),
440
- )
441
- .into()
442
- };
443
-
444
- progress = py
445
- .detach(|| call.resume(result, print_output.reborrow()))
446
- .map_err(|e| MontyError::new_err(py, e))?;
447
- }
448
- }
449
- }
450
- }
451
- }
452
-
453
- /// pyclass doesn't support generic types, hence hard coding the generics
454
- #[derive(Debug)]
455
- pub(crate) enum EitherProgress {
456
- NoLimit(RunProgress<PySignalTracker<NoLimitTracker>>),
457
- Limited(RunProgress<PySignalTracker<LimitedTracker>>),
458
- /// REPL progress with back-reference to the owning `PyMontyRepl` for auto-restore.
459
- ReplNoLimit(ReplProgress<PySignalTracker<NoLimitTracker>>, Py<PyMontyRepl>),
460
- /// REPL progress with back-reference to the owning `PyMontyRepl` for auto-restore.
461
- ReplLimited(ReplProgress<PySignalTracker<LimitedTracker>>, Py<PyMontyRepl>),
462
- }
463
-
464
- impl EitherProgress {
465
- /// Converts progress into the appropriate Python object:
466
- /// function snapshot, name lookup snapshot, future snapshot, or complete.
467
- pub(crate) fn progress_or_complete(
468
- self,
469
- py: Python<'_>,
470
- script_name: String,
471
- print_callback: Option<Py<PyAny>>,
472
- dc_registry: DcRegistry,
473
- ) -> PyResult<Bound<'_, PyAny>> {
474
- match self {
475
- Self::NoLimit(p) => run_progress_to_py(py, p, script_name, print_callback, dc_registry),
476
- Self::Limited(p) => run_progress_to_py(py, p, script_name, print_callback, dc_registry),
477
- Self::ReplNoLimit(p, owner) => repl_progress_to_py(py, p, script_name, print_callback, dc_registry, owner),
478
- Self::ReplLimited(p, owner) => repl_progress_to_py(py, p, script_name, print_callback, dc_registry, owner),
479
- }
480
- }
481
- }
482
-
483
- /// Converts a `RunProgress<T>` into the appropriate Python snapshot type.
484
- fn run_progress_to_py<T: ResourceTracker>(
485
- py: Python<'_>,
486
- progress: RunProgress<T>,
487
- script_name: String,
488
- print_callback: Option<Py<PyAny>>,
489
- dc_registry: DcRegistry,
490
- ) -> PyResult<Bound<'_, PyAny>>
491
- where
492
- EitherFunctionSnapshot: FromFunctionCall<T> + FromOsCall<T>,
493
- EitherLookupSnapshot: FromNameLookup<T>,
494
- EitherFutureSnapshot: FromResolveFutures<T>,
495
- {
496
- match progress {
497
- RunProgress::Complete(result) => PyMontyComplete::create(py, &result, &dc_registry),
498
- RunProgress::FunctionCall(call) => {
499
- PyFunctionSnapshot::function_call(py, call, script_name, print_callback, dc_registry)
500
- }
501
- RunProgress::OsCall(call) => PyFunctionSnapshot::os_call(py, call, script_name, print_callback, dc_registry),
502
- RunProgress::ResolveFutures(state) => {
503
- PyFutureSnapshot::new_py_any(py, state, script_name, print_callback, dc_registry)
504
- }
505
- RunProgress::NameLookup(lookup) => {
506
- PyNameLookupSnapshot::new_py_any(py, lookup, script_name, print_callback, dc_registry)
507
- }
508
- }
509
- }
510
-
511
- /// Converts a `ReplProgress<T>` into the appropriate Python snapshot type.
512
- ///
513
- /// On completion, restores the REPL state into `repl_owner` before returning `MontyComplete`.
514
- /// The `repl_owner` is propagated into snapshot enum variants so the chain can continue.
515
- fn repl_progress_to_py<T: ResourceTracker>(
516
- py: Python<'_>,
517
- progress: ReplProgress<T>,
518
- script_name: String,
519
- print_callback: Option<Py<PyAny>>,
520
- dc_registry: DcRegistry,
521
- repl_owner: Py<PyMontyRepl>,
522
- ) -> PyResult<Bound<'_, PyAny>>
523
- where
524
- EitherFunctionSnapshot: FromReplFunctionCall<T> + FromReplOsCall<T>,
525
- EitherLookupSnapshot: FromReplNameLookup<T>,
526
- EitherFutureSnapshot: FromReplResolveFutures<T>,
527
- EitherRepl: FromCoreRepl<T>,
528
- {
529
- match progress {
530
- ReplProgress::Complete { repl, value } => {
531
- repl_owner.get().put_repl(EitherRepl::from_core(repl));
532
- PyMontyComplete::create(py, &value, &dc_registry)
533
- }
534
- ReplProgress::FunctionCall(call) => {
535
- PyFunctionSnapshot::repl_function_call(py, call, script_name, print_callback, dc_registry, repl_owner)
536
- }
537
- ReplProgress::OsCall(call) => {
538
- PyFunctionSnapshot::repl_os_call(py, call, script_name, print_callback, dc_registry, repl_owner)
539
- }
540
- ReplProgress::NameLookup(lookup) => {
541
- let variable_name = lookup.name.clone();
542
- PyNameLookupSnapshot::repl_name_lookup(
543
- py,
544
- lookup,
545
- script_name,
546
- print_callback,
547
- dc_registry,
548
- repl_owner,
549
- variable_name,
550
- )
551
- }
552
- ReplProgress::ResolveFutures(state) => {
553
- PyFutureSnapshot::repl_resolve_futures(py, state, script_name, print_callback, dc_registry, repl_owner)
554
- }
555
- }
556
- }
557
-
558
- /// Runtime execution snapshot, holds either a `FunctionCall` or `OsCall` for both
559
- /// resource tracker variants since pyclass structs can't be generic.
560
- ///
561
- /// Also holds REPL variants (`ReplFunctionCall`, `ReplOsCall`) for `MontyRepl.feed_start()`.
562
- /// REPL variants carry a `Py<PyMontyRepl>` back-reference so the REPL can be auto-restored
563
- /// on completion or error.
564
- ///
565
- /// Used internally by `PyFunctionSnapshot` to store execution state. Both `FunctionCall`
566
- /// and `OsCall` have the same `resume()` signature, so we dispatch to the appropriate
567
- /// inner type based on the variant.
568
- ///
569
- /// The `Done` variant indicates the snapshot has been consumed.
570
- ///
571
- /// Serde: REPL variants serialize as their non-REPL counterparts (stripping the owner).
572
- /// Deserialization always produces non-REPL variants.
573
- #[derive(Debug)]
574
- pub(crate) enum EitherFunctionSnapshot {
575
- // Run variants (from Monty.start())
576
- NoLimitFn(FunctionCall<PySignalTracker<NoLimitTracker>>),
577
- NoLimitOs(OsCall<PySignalTracker<NoLimitTracker>>),
578
- LimitedFn(FunctionCall<PySignalTracker<LimitedTracker>>),
579
- LimitedOs(OsCall<PySignalTracker<LimitedTracker>>),
580
- // REPL variants (from MontyRepl.feed_start()) — carry the REPL owner
581
- ReplNoLimitFn(ReplFunctionCall<PySignalTracker<NoLimitTracker>>, Py<PyMontyRepl>),
582
- ReplNoLimitOs(ReplOsCall<PySignalTracker<NoLimitTracker>>, Py<PyMontyRepl>),
583
- ReplLimitedFn(ReplFunctionCall<PySignalTracker<LimitedTracker>>, Py<PyMontyRepl>),
584
- ReplLimitedOs(ReplOsCall<PySignalTracker<LimitedTracker>>, Py<PyMontyRepl>),
585
- /// Sentinel indicating the snapshot has been consumed via `resume()`.
586
- Done,
587
- }
588
-
589
- /// Helper trait for wrapping `FunctionCall<T>` into `EitherFunctionSnapshot`.
590
- trait FromFunctionCall<T: ResourceTracker> {
591
- /// Wraps a function call into the appropriate variant.
592
- fn from_fn(call: FunctionCall<T>) -> Self;
593
- }
594
-
595
- impl FromFunctionCall<PySignalTracker<NoLimitTracker>> for EitherFunctionSnapshot {
596
- fn from_fn(call: FunctionCall<PySignalTracker<NoLimitTracker>>) -> Self {
597
- Self::NoLimitFn(call)
598
- }
599
- }
600
-
601
- impl FromFunctionCall<PySignalTracker<LimitedTracker>> for EitherFunctionSnapshot {
602
- fn from_fn(call: FunctionCall<PySignalTracker<LimitedTracker>>) -> Self {
603
- Self::LimitedFn(call)
604
- }
605
- }
606
-
607
- /// Helper trait for wrapping `OsCall<T>` into `EitherFunctionSnapshot`.
608
- trait FromOsCall<T: ResourceTracker> {
609
- /// Wraps an OS call into the appropriate variant.
610
- fn from_os(call: OsCall<T>) -> Self;
611
- }
612
-
613
- impl FromOsCall<PySignalTracker<NoLimitTracker>> for EitherFunctionSnapshot {
614
- fn from_os(call: OsCall<PySignalTracker<NoLimitTracker>>) -> Self {
615
- Self::NoLimitOs(call)
616
- }
617
- }
618
-
619
- impl FromOsCall<PySignalTracker<LimitedTracker>> for EitherFunctionSnapshot {
620
- fn from_os(call: OsCall<PySignalTracker<LimitedTracker>>) -> Self {
621
- Self::LimitedOs(call)
622
- }
623
- }
624
-
625
- /// Helper trait for wrapping `ReplFunctionCall<T>` into `EitherFunctionSnapshot`.
626
- trait FromReplFunctionCall<T: ResourceTracker> {
627
- /// Wraps a REPL function call into the appropriate variant.
628
- fn from_repl_fn(call: ReplFunctionCall<T>, owner: Py<PyMontyRepl>) -> Self;
629
- }
630
-
631
- impl FromReplFunctionCall<PySignalTracker<NoLimitTracker>> for EitherFunctionSnapshot {
632
- fn from_repl_fn(call: ReplFunctionCall<PySignalTracker<NoLimitTracker>>, owner: Py<PyMontyRepl>) -> Self {
633
- Self::ReplNoLimitFn(call, owner)
634
- }
635
- }
636
-
637
- impl FromReplFunctionCall<PySignalTracker<LimitedTracker>> for EitherFunctionSnapshot {
638
- fn from_repl_fn(call: ReplFunctionCall<PySignalTracker<LimitedTracker>>, owner: Py<PyMontyRepl>) -> Self {
639
- Self::ReplLimitedFn(call, owner)
640
- }
641
- }
642
-
643
- /// Helper trait for wrapping `ReplOsCall<T>` into `EitherFunctionSnapshot`.
644
- trait FromReplOsCall<T: ResourceTracker> {
645
- /// Wraps a REPL OS call into the appropriate variant.
646
- fn from_repl_os(call: ReplOsCall<T>, owner: Py<PyMontyRepl>) -> Self;
647
- }
648
-
649
- impl FromReplOsCall<PySignalTracker<NoLimitTracker>> for EitherFunctionSnapshot {
650
- fn from_repl_os(call: ReplOsCall<PySignalTracker<NoLimitTracker>>, owner: Py<PyMontyRepl>) -> Self {
651
- Self::ReplNoLimitOs(call, owner)
652
- }
653
- }
654
-
655
- impl FromReplOsCall<PySignalTracker<LimitedTracker>> for EitherFunctionSnapshot {
656
- fn from_repl_os(call: ReplOsCall<PySignalTracker<LimitedTracker>>, owner: Py<PyMontyRepl>) -> Self {
657
- Self::ReplLimitedOs(call, owner)
658
- }
659
- }
660
-
661
- /// Snapshot generated during execution when monty yields to the host for a function call.
662
- #[pyclass(name = "FunctionSnapshot", module = "pydantic_monty")]
663
- #[derive(Debug)]
664
- pub struct PyFunctionSnapshot {
665
- snapshot: Mutex<EitherFunctionSnapshot>,
666
- print_callback: Option<Py<PyAny>>,
667
- dc_registry: DcRegistry,
668
-
669
- /// Name of the script being executed
670
- #[pyo3(get)]
671
- pub script_name: String,
672
-
673
- /// Whether this call refers to an OS function
674
- #[pyo3(get)]
675
- pub is_os_function: bool,
676
-
677
- /// Whether this call is a dataclass method call (first arg is `self`)
678
- #[pyo3(get)]
679
- pub is_method_call: bool,
680
-
681
- /// The name of the function being called.
682
- #[pyo3(get)]
683
- pub function_name: String,
684
- /// The positional arguments passed to the function.
685
- #[pyo3(get)]
686
- pub args: Py<PyTuple>,
687
- /// The keyword arguments passed to the function (key, value pairs).
688
- #[pyo3(get)]
689
- pub kwargs: Py<PyDict>,
690
- /// The unique identifier for this call
691
- #[pyo3(get)]
692
- pub call_id: u32,
693
- }
694
-
695
- impl PyFunctionSnapshot {
696
- /// Creates a `PyFunctionSnapshot` for an external function call.
697
- ///
698
- /// Extracts display fields from the `FunctionCall` before moving it into
699
- /// `EitherSnapshot` via the provided `wrap` closure.
700
- fn function_call<T: ResourceTracker>(
701
- py: Python<'_>,
702
- call: FunctionCall<T>,
703
- script_name: String,
704
- print_callback: Option<Py<PyAny>>,
705
- dc_registry: DcRegistry,
706
- ) -> PyResult<Bound<'_, PyAny>>
707
- where
708
- EitherFunctionSnapshot: FromFunctionCall<T>,
709
- {
710
- let function_name = call.function_name.clone();
711
- let call_id = call.call_id;
712
- let method_call = call.method_call;
713
- let items: PyResult<Vec<Py<PyAny>>> = call
714
- .args
715
- .iter()
716
- .map(|item| monty_to_py(py, item, &dc_registry))
717
- .collect();
718
- let dict = PyDict::new(py);
719
- for (k, v) in &call.kwargs {
720
- dict.set_item(monty_to_py(py, k, &dc_registry)?, monty_to_py(py, v, &dc_registry)?)?;
721
- }
722
-
723
- let slf = Self {
724
- snapshot: Mutex::new(EitherFunctionSnapshot::from_fn(call)),
725
- print_callback,
726
- script_name,
727
- is_os_function: false,
728
- is_method_call: method_call,
729
- function_name,
730
- args: PyTuple::new(py, items?)?.unbind(),
731
- kwargs: dict.unbind(),
732
- call_id,
733
- dc_registry,
734
- };
735
- slf.into_bound_py_any(py)
736
- }
737
-
738
- /// Creates a `PyFunctionSnapshot` for an OS-level call.
739
- ///
740
- /// Extracts display fields from the `OsCall` before moving it into
741
- /// `EitherSnapshot` via the provided `wrap` closure.
742
- fn os_call<T: ResourceTracker>(
743
- py: Python<'_>,
744
- call: OsCall<T>,
745
- script_name: String,
746
- print_callback: Option<Py<PyAny>>,
747
- dc_registry: DcRegistry,
748
- ) -> PyResult<Bound<'_, PyAny>>
749
- where
750
- EitherFunctionSnapshot: FromOsCall<T>,
751
- {
752
- let function_name = call.function.to_string();
753
- let call_id = call.call_id;
754
- let items: PyResult<Vec<Py<PyAny>>> = call
755
- .args
756
- .iter()
757
- .map(|item| monty_to_py(py, item, &dc_registry))
758
- .collect();
759
- let dict = PyDict::new(py);
760
- for (k, v) in &call.kwargs {
761
- dict.set_item(monty_to_py(py, k, &dc_registry)?, monty_to_py(py, v, &dc_registry)?)?;
762
- }
763
-
764
- let slf = Self {
765
- snapshot: Mutex::new(EitherFunctionSnapshot::from_os(call)),
766
- print_callback,
767
- script_name,
768
- is_os_function: true,
769
- is_method_call: false,
770
- function_name,
771
- args: PyTuple::new(py, items?)?.unbind(),
772
- kwargs: dict.unbind(),
773
- call_id,
774
- dc_registry,
775
- };
776
- slf.into_bound_py_any(py)
777
- }
778
-
779
- /// Creates a `PyFunctionSnapshot` for a REPL external function call.
780
- fn repl_function_call<T: ResourceTracker>(
781
- py: Python<'_>,
782
- call: ReplFunctionCall<T>,
783
- script_name: String,
784
- print_callback: Option<Py<PyAny>>,
785
- dc_registry: DcRegistry,
786
- repl_owner: Py<PyMontyRepl>,
787
- ) -> PyResult<Bound<'_, PyAny>>
788
- where
789
- EitherFunctionSnapshot: FromReplFunctionCall<T>,
790
- {
791
- let function_name = call.function_name.clone();
792
- let call_id = call.call_id;
793
- let method_call = call.method_call;
794
- let items: PyResult<Vec<Py<PyAny>>> = call
795
- .args
796
- .iter()
797
- .map(|item| monty_to_py(py, item, &dc_registry))
798
- .collect();
799
- let dict = PyDict::new(py);
800
- for (k, v) in &call.kwargs {
801
- dict.set_item(monty_to_py(py, k, &dc_registry)?, monty_to_py(py, v, &dc_registry)?)?;
802
- }
803
-
804
- let slf = Self {
805
- snapshot: Mutex::new(EitherFunctionSnapshot::from_repl_fn(call, repl_owner)),
806
- print_callback,
807
- script_name,
808
- is_os_function: false,
809
- is_method_call: method_call,
810
- function_name,
811
- args: PyTuple::new(py, items?)?.unbind(),
812
- kwargs: dict.unbind(),
813
- call_id,
814
- dc_registry,
815
- };
816
- slf.into_bound_py_any(py)
817
- }
818
-
819
- /// Creates a `PyFunctionSnapshot` for a REPL OS-level call.
820
- fn repl_os_call<T: ResourceTracker>(
821
- py: Python<'_>,
822
- call: ReplOsCall<T>,
823
- script_name: String,
824
- print_callback: Option<Py<PyAny>>,
825
- dc_registry: DcRegistry,
826
- repl_owner: Py<PyMontyRepl>,
827
- ) -> PyResult<Bound<'_, PyAny>>
828
- where
829
- EitherFunctionSnapshot: FromReplOsCall<T>,
830
- {
831
- let function_name = call.function.to_string();
832
- let call_id = call.call_id;
833
- let items: PyResult<Vec<Py<PyAny>>> = call
834
- .args
835
- .iter()
836
- .map(|item| monty_to_py(py, item, &dc_registry))
837
- .collect();
838
- let dict = PyDict::new(py);
839
- for (k, v) in &call.kwargs {
840
- dict.set_item(monty_to_py(py, k, &dc_registry)?, monty_to_py(py, v, &dc_registry)?)?;
841
- }
842
-
843
- let slf = Self {
844
- snapshot: Mutex::new(EitherFunctionSnapshot::from_repl_os(call, repl_owner)),
845
- print_callback,
846
- script_name,
847
- is_os_function: true,
848
- is_method_call: false,
849
- function_name,
850
- args: PyTuple::new(py, items?)?.unbind(),
851
- kwargs: dict.unbind(),
852
- call_id,
853
- dc_registry,
854
- };
855
- slf.into_bound_py_any(py)
856
- }
857
-
858
- /// Constructs a `PyFunctionSnapshot` from deserialized parts.
859
- ///
860
- /// Used by `load_snapshot` and `load_repl_snapshot` to reconstruct snapshot objects.
861
- #[expect(clippy::too_many_arguments)]
862
- pub(crate) fn from_deserialized(
863
- py: Python<'_>,
864
- snapshot: EitherFunctionSnapshot,
865
- print_callback: Option<Py<PyAny>>,
866
- dc_registry: DcRegistry,
867
- script_name: String,
868
- is_os_function: bool,
869
- is_method_call: bool,
870
- function_name: String,
871
- args: Py<PyTuple>,
872
- kwargs: Py<PyDict>,
873
- call_id: u32,
874
- ) -> PyResult<Bound<'_, PyAny>> {
875
- let slf = Self {
876
- snapshot: Mutex::new(snapshot),
877
- print_callback,
878
- dc_registry,
879
- script_name,
880
- is_os_function,
881
- is_method_call,
882
- function_name,
883
- args,
884
- kwargs,
885
- call_id,
886
- };
887
- slf.into_bound_py_any(py)
888
- }
889
- }
890
-
891
- #[pymethods]
892
- impl PyFunctionSnapshot {
893
- /// Resumes execution with either a return value, exception or future.
894
- ///
895
- /// Exactly one of `return_value`, `exception` or `future` must be provided as a keyword argument.
896
- ///
897
- /// # Raises
898
- /// * `TypeError` if both arguments are provided, or neither
899
- /// * `RuntimeError` if the snapshot has already been resumed
900
- #[pyo3(signature = (**kwargs))]
901
- pub fn resume<'py>(&self, py: Python<'py>, kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<Bound<'py, PyAny>> {
902
- const ARGS_ERROR: &str = "resume() accepts either return_value or exception, not both";
903
-
904
- let mut snapshot = self
905
- .snapshot
906
- .lock()
907
- .map_err(|_| PyRuntimeError::new_err("Snapshot is currently being resumed by another thread"))?;
908
-
909
- let snapshot = std::mem::replace(&mut *snapshot, EitherFunctionSnapshot::Done);
910
- let Some(kwargs) = kwargs else {
911
- return Err(PyTypeError::new_err(ARGS_ERROR));
912
- };
913
- let external_result = extract_external_result(py, kwargs, ARGS_ERROR, &self.dc_registry, self.call_id)?;
914
-
915
- // Build print writer before detaching - clone_ref needs py token
916
- let mut print_cb;
917
- let print_writer = match &self.print_callback {
918
- Some(cb) => {
919
- print_cb = CallbackStringPrint::from_py(cb.clone_ref(py));
920
- PrintWriter::Callback(&mut print_cb)
921
- }
922
- None => PrintWriter::Stdout,
923
- };
924
- // wrap print_writer in SendWrapper so that it can be accessed inside the py.detach calls despite
925
- // no `Send` bound - py.detach() is overly restrictive to prevent `Bound` types going inside
926
- let mut print_writer = SendWrapper::new(print_writer);
927
-
928
- let progress = match snapshot {
929
- EitherFunctionSnapshot::NoLimitFn(call) => {
930
- let result = py.detach(|| call.resume(external_result, print_writer.reborrow()));
931
- EitherProgress::NoLimit(result.map_err(|e| MontyError::new_err(py, e))?)
932
- }
933
- EitherFunctionSnapshot::NoLimitOs(call) => {
934
- let result = py.detach(|| call.resume(external_result, print_writer.reborrow()));
935
- EitherProgress::NoLimit(result.map_err(|e| MontyError::new_err(py, e))?)
936
- }
937
- EitherFunctionSnapshot::LimitedFn(call) => {
938
- let result = py.detach(|| call.resume(external_result, print_writer.reborrow()));
939
- EitherProgress::Limited(result.map_err(|e| MontyError::new_err(py, e))?)
940
- }
941
- EitherFunctionSnapshot::LimitedOs(call) => {
942
- let result = py.detach(|| call.resume(external_result, print_writer.reborrow()));
943
- EitherProgress::Limited(result.map_err(|e| MontyError::new_err(py, e))?)
944
- }
945
- EitherFunctionSnapshot::ReplNoLimitFn(call, owner) => {
946
- let result = py
947
- .detach(|| call.resume(external_result, print_writer.reborrow()))
948
- .map_err(|e| restore_repl_from_repl_start_error(py, &owner, *e))?;
949
- EitherProgress::ReplNoLimit(result, owner)
950
- }
951
- EitherFunctionSnapshot::ReplNoLimitOs(call, owner) => {
952
- let result = py
953
- .detach(|| call.resume(external_result, print_writer.reborrow()))
954
- .map_err(|e| restore_repl_from_repl_start_error(py, &owner, *e))?;
955
- EitherProgress::ReplNoLimit(result, owner)
956
- }
957
- EitherFunctionSnapshot::ReplLimitedFn(call, owner) => {
958
- let result = py
959
- .detach(|| call.resume(external_result, print_writer.reborrow()))
960
- .map_err(|e| restore_repl_from_repl_start_error(py, &owner, *e))?;
961
- EitherProgress::ReplLimited(result, owner)
962
- }
963
- EitherFunctionSnapshot::ReplLimitedOs(call, owner) => {
964
- let result = py
965
- .detach(|| call.resume(external_result, print_writer.reborrow()))
966
- .map_err(|e| restore_repl_from_repl_start_error(py, &owner, *e))?;
967
- EitherProgress::ReplLimited(result, owner)
968
- }
969
- EitherFunctionSnapshot::Done => return Err(PyRuntimeError::new_err("Progress already resumed")),
970
- };
971
-
972
- let dc_registry = self.dc_registry.clone_ref(py);
973
- progress.progress_or_complete(
974
- py,
975
- self.script_name.clone(),
976
- self.print_callback.as_ref().map(|cb| cb.clone_ref(py)),
977
- dc_registry,
978
- )
979
- }
980
-
981
- /// Serializes the FunctionSnapshot instance to a binary format.
982
- ///
983
- /// The serialized data can be stored and later restored with `load_snapshot()`
984
- /// or `load_repl_snapshot()`. REPL snapshots automatically include the REPL state.
985
- ///
986
- /// Note: The `print_callback` is not serialized and must be re-provided when loading.
987
- ///
988
- /// # Returns
989
- /// Bytes containing the serialized FunctionSnapshot instance.
990
- ///
991
- /// # Raises
992
- /// `ValueError` if serialization fails.
993
- /// `RuntimeError` if the progress has already been resumed.
994
- fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
995
- let bytes = crate::serialization::dump_function_snapshot(
996
- py,
997
- &self.snapshot,
998
- &self.script_name,
999
- self.is_os_function,
1000
- self.is_method_call,
1001
- &self.function_name,
1002
- &self.args,
1003
- &self.kwargs,
1004
- self.call_id,
1005
- &self.dc_registry,
1006
- )?;
1007
- Ok(PyBytes::new(py, &bytes))
1008
- }
1009
-
1010
- fn __repr__(&self, py: Python<'_>) -> PyResult<String> {
1011
- Ok(format!(
1012
- "FunctionSnapshot(script_name='{}', function_name='{}', args={}, kwargs={})",
1013
- self.script_name,
1014
- self.function_name,
1015
- self.args.bind(py).repr()?,
1016
- self.kwargs.bind(py).repr()?
1017
- ))
1018
- }
1019
- }
1020
-
1021
- /// Runtime execution snapshot, holds a `NameLookup` for both
1022
- /// resource tracker variants since pyclass structs can't be generic.
1023
- ///
1024
- /// Also holds REPL variants with `Py<PyMontyRepl>` for `MontyRepl.feed_start()`.
1025
- ///
1026
- /// The `Done` variant indicates the snapshot has been consumed.
1027
- #[derive(Debug)]
1028
- pub(crate) enum EitherLookupSnapshot {
1029
- NoLimit(NameLookup<PySignalTracker<NoLimitTracker>>),
1030
- Limited(NameLookup<PySignalTracker<LimitedTracker>>),
1031
- ReplNoLimit(ReplNameLookup<PySignalTracker<NoLimitTracker>>, Py<PyMontyRepl>),
1032
- ReplLimited(ReplNameLookup<PySignalTracker<LimitedTracker>>, Py<PyMontyRepl>),
1033
- /// Sentinel indicating the snapshot has been consumed via `resume()`.
1034
- Done,
1035
- }
1036
-
1037
- /// Helper trait for wrapping `NameLookup<T>` into `EitherLookupSnapshot`.
1038
- trait FromNameLookup<T: ResourceTracker> {
1039
- /// Wraps a name lookup into the appropriate variant.
1040
- fn from_name_lookup(lookup: NameLookup<T>) -> Self;
1041
- }
1042
-
1043
- impl FromNameLookup<PySignalTracker<NoLimitTracker>> for EitherLookupSnapshot {
1044
- fn from_name_lookup(lookup: NameLookup<PySignalTracker<NoLimitTracker>>) -> Self {
1045
- Self::NoLimit(lookup)
1046
- }
1047
- }
1048
-
1049
- impl FromNameLookup<PySignalTracker<LimitedTracker>> for EitherLookupSnapshot {
1050
- fn from_name_lookup(lookup: NameLookup<PySignalTracker<LimitedTracker>>) -> Self {
1051
- Self::Limited(lookup)
1052
- }
1053
- }
1054
-
1055
- /// Helper trait for wrapping `ReplNameLookup<T>` into `EitherLookupSnapshot`.
1056
- trait FromReplNameLookup<T: ResourceTracker> {
1057
- /// Wraps a REPL name lookup into the appropriate variant.
1058
- fn from_repl_name_lookup(lookup: ReplNameLookup<T>, owner: Py<PyMontyRepl>) -> Self;
1059
- }
1060
-
1061
- impl FromReplNameLookup<PySignalTracker<NoLimitTracker>> for EitherLookupSnapshot {
1062
- fn from_repl_name_lookup(lookup: ReplNameLookup<PySignalTracker<NoLimitTracker>>, owner: Py<PyMontyRepl>) -> Self {
1063
- Self::ReplNoLimit(lookup, owner)
1064
- }
1065
- }
1066
-
1067
- impl FromReplNameLookup<PySignalTracker<LimitedTracker>> for EitherLookupSnapshot {
1068
- fn from_repl_name_lookup(lookup: ReplNameLookup<PySignalTracker<LimitedTracker>>, owner: Py<PyMontyRepl>) -> Self {
1069
- Self::ReplLimited(lookup, owner)
1070
- }
1071
- }
1072
-
1073
- /// Snapshot generated during execution when monty yields to the host for a name lookup.
1074
- #[pyclass(name = "NameLookupSnapshot", module = "pydantic_monty")]
1075
- #[derive(Debug)]
1076
- pub struct PyNameLookupSnapshot {
1077
- snapshot: Mutex<EitherLookupSnapshot>,
1078
- print_callback: Option<Py<PyAny>>,
1079
- dc_registry: DcRegistry,
1080
-
1081
- /// Name of the script being executed
1082
- #[pyo3(get)]
1083
- pub script_name: String,
1084
-
1085
- /// Name of the variable being looked up
1086
- #[pyo3(get)]
1087
- pub variable_name: String,
1088
- }
1089
-
1090
- impl PyNameLookupSnapshot {
1091
- /// Creates a `PyNameLookupSnapshot` for an external function call.
1092
- ///
1093
- /// Extracts display fields from the `FunctionCall` before moving it into
1094
- /// `EitherSnapshot` via the provided `wrap` closure.
1095
- fn new_py_any<T: ResourceTracker>(
1096
- py: Python<'_>,
1097
- lookup: NameLookup<T>,
1098
- script_name: String,
1099
- print_callback: Option<Py<PyAny>>,
1100
- dc_registry: DcRegistry,
1101
- ) -> PyResult<Bound<'_, PyAny>>
1102
- where
1103
- EitherLookupSnapshot: FromNameLookup<T>,
1104
- {
1105
- let variable_name = lookup.name.clone();
1106
-
1107
- let slf = Self {
1108
- snapshot: Mutex::new(EitherLookupSnapshot::from_name_lookup(lookup)),
1109
- print_callback,
1110
- dc_registry,
1111
- script_name,
1112
- variable_name,
1113
- };
1114
- slf.into_bound_py_any(py)
1115
- }
1116
-
1117
- /// Creates a `PyNameLookupSnapshot` for a REPL name lookup.
1118
- fn repl_name_lookup<T: ResourceTracker>(
1119
- py: Python<'_>,
1120
- lookup: ReplNameLookup<T>,
1121
- script_name: String,
1122
- print_callback: Option<Py<PyAny>>,
1123
- dc_registry: DcRegistry,
1124
- repl_owner: Py<PyMontyRepl>,
1125
- variable_name: String,
1126
- ) -> PyResult<Bound<'_, PyAny>>
1127
- where
1128
- EitherLookupSnapshot: FromReplNameLookup<T>,
1129
- {
1130
- let slf = Self {
1131
- snapshot: Mutex::new(EitherLookupSnapshot::from_repl_name_lookup(lookup, repl_owner)),
1132
- print_callback,
1133
- dc_registry,
1134
- script_name,
1135
- variable_name,
1136
- };
1137
- slf.into_bound_py_any(py)
1138
- }
1139
-
1140
- /// Constructs a `PyNameLookupSnapshot` from deserialized parts.
1141
- pub(crate) fn from_deserialized(
1142
- py: Python<'_>,
1143
- snapshot: EitherLookupSnapshot,
1144
- print_callback: Option<Py<PyAny>>,
1145
- dc_registry: DcRegistry,
1146
- script_name: String,
1147
- variable_name: String,
1148
- ) -> PyResult<Bound<'_, PyAny>> {
1149
- let slf = Self {
1150
- snapshot: Mutex::new(snapshot),
1151
- print_callback,
1152
- dc_registry,
1153
- script_name,
1154
- variable_name,
1155
- };
1156
- slf.into_bound_py_any(py)
1157
- }
1158
- }
1159
-
1160
- #[pymethods]
1161
- impl PyNameLookupSnapshot {
1162
- /// Resumes execution with either a value or undefined.
1163
- #[pyo3(signature = (**kwargs))]
1164
- pub fn resume<'py>(&self, py: Python<'py>, kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<Bound<'py, PyAny>> {
1165
- let mut snapshot = self
1166
- .snapshot
1167
- .lock()
1168
- .map_err(|_| PyRuntimeError::new_err("Snapshot is currently being resumed by another thread"))?;
1169
-
1170
- let snapshot = std::mem::replace(&mut *snapshot, EitherLookupSnapshot::Done);
1171
- let lookup_result = if let Some(kwargs) = kwargs
1172
- && let Some(value) = kwargs.get_item(intern!(py, "value"))?
1173
- {
1174
- NameLookupResult::Value(py_to_monty(&value, &self.dc_registry)?)
1175
- } else {
1176
- NameLookupResult::Undefined
1177
- };
1178
-
1179
- // Build print writer before detaching - clone_ref needs py token
1180
- let mut print_cb;
1181
- let print_writer = match &self.print_callback {
1182
- Some(cb) => {
1183
- print_cb = CallbackStringPrint::from_py(cb.clone_ref(py));
1184
- PrintWriter::Callback(&mut print_cb)
1185
- }
1186
- None => PrintWriter::Stdout,
1187
- };
1188
- let mut print_writer = SendWrapper::new(print_writer);
1189
-
1190
- let progress = match snapshot {
1191
- EitherLookupSnapshot::NoLimit(snapshot) => {
1192
- let result = py.detach(|| snapshot.resume(lookup_result, print_writer.reborrow()));
1193
- EitherProgress::NoLimit(result.map_err(|e| MontyError::new_err(py, e))?)
1194
- }
1195
- EitherLookupSnapshot::Limited(snapshot) => {
1196
- let result = py.detach(|| snapshot.resume(lookup_result, print_writer.reborrow()));
1197
- EitherProgress::Limited(result.map_err(|e| MontyError::new_err(py, e))?)
1198
- }
1199
- EitherLookupSnapshot::ReplNoLimit(snapshot, owner) => {
1200
- let result = py
1201
- .detach(|| snapshot.resume(lookup_result, print_writer.reborrow()))
1202
- .map_err(|e| restore_repl_from_repl_start_error(py, &owner, *e))?;
1203
- EitherProgress::ReplNoLimit(result, owner)
1204
- }
1205
- EitherLookupSnapshot::ReplLimited(snapshot, owner) => {
1206
- let result = py
1207
- .detach(|| snapshot.resume(lookup_result, print_writer.reborrow()))
1208
- .map_err(|e| restore_repl_from_repl_start_error(py, &owner, *e))?;
1209
- EitherProgress::ReplLimited(result, owner)
1210
- }
1211
- EitherLookupSnapshot::Done => return Err(PyRuntimeError::new_err("Progress already resumed")),
1212
- };
1213
-
1214
- // Clone the Arc handle for the next snapshot/complete
1215
- let dc_registry = self.dc_registry.clone_ref(py);
1216
- progress.progress_or_complete(
1217
- py,
1218
- self.script_name.clone(),
1219
- self.print_callback.as_ref().map(|cb| cb.clone_ref(py)),
1220
- dc_registry,
1221
- )
1222
- }
1223
-
1224
- /// Serializes the NameLookupSnapshot instance to a binary format.
1225
- ///
1226
- /// The serialized data can be stored and later restored with `load_snapshot()`
1227
- /// or `load_repl_snapshot()`. REPL snapshots automatically include the REPL state.
1228
- ///
1229
- /// Note: The `print_callback` is not serialized and must be re-provided when loading.
1230
- ///
1231
- /// # Returns
1232
- /// Bytes containing the serialized NameLookupSnapshot instance.
1233
- ///
1234
- /// # Raises
1235
- /// `ValueError` if serialization fails.
1236
- /// `RuntimeError` if the progress has already been resumed.
1237
- fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
1238
- let bytes = crate::serialization::dump_lookup_snapshot(&self.snapshot, &self.script_name, &self.variable_name)?;
1239
- Ok(PyBytes::new(py, &bytes))
1240
- }
1241
-
1242
- fn __repr__(&self) -> String {
1243
- format!(
1244
- "NameLookupSnapshot(script_name='{}', variable_name={:?})",
1245
- self.script_name, self.variable_name
1246
- )
1247
- }
1248
- }
1249
-
1250
- /// Holds a `ResolveFutures` for either resource tracker variant.
1251
- ///
1252
- /// Also holds REPL variants with `Py<PyMontyRepl>` for `MontyRepl.feed_start()`.
1253
- ///
1254
- /// Used internally by `PyFutureSnapshot` to store execution state when
1255
- /// awaiting resolution of pending async external calls.
1256
- #[derive(Debug)]
1257
- pub(crate) enum EitherFutureSnapshot {
1258
- NoLimit(ResolveFutures<PySignalTracker<NoLimitTracker>>),
1259
- Limited(ResolveFutures<PySignalTracker<LimitedTracker>>),
1260
- ReplNoLimit(ReplResolveFutures<PySignalTracker<NoLimitTracker>>, Py<PyMontyRepl>),
1261
- ReplLimited(ReplResolveFutures<PySignalTracker<LimitedTracker>>, Py<PyMontyRepl>),
1262
- /// Sentinel indicating the snapshot has been consumed via `resume()`.
1263
- Done,
1264
- }
1265
-
1266
- /// Helper trait for wrapping `ResolveFutures<T>` into `EitherFutureSnapshot`.
1267
- trait FromResolveFutures<T: ResourceTracker> {
1268
- /// Wraps a resolve-futures state into the appropriate variant.
1269
- fn from_resolve_futures(state: ResolveFutures<T>) -> Self;
1270
- }
1271
-
1272
- impl FromResolveFutures<PySignalTracker<NoLimitTracker>> for EitherFutureSnapshot {
1273
- fn from_resolve_futures(state: ResolveFutures<PySignalTracker<NoLimitTracker>>) -> Self {
1274
- Self::NoLimit(state)
1275
- }
1276
- }
1277
-
1278
- impl FromResolveFutures<PySignalTracker<LimitedTracker>> for EitherFutureSnapshot {
1279
- fn from_resolve_futures(state: ResolveFutures<PySignalTracker<LimitedTracker>>) -> Self {
1280
- Self::Limited(state)
1281
- }
1282
- }
1283
-
1284
- /// Helper trait for wrapping `ReplResolveFutures<T>` into `EitherFutureSnapshot`.
1285
- trait FromReplResolveFutures<T: ResourceTracker> {
1286
- /// Wraps a REPL resolve-futures state into the appropriate variant.
1287
- fn from_repl_resolve_futures(state: ReplResolveFutures<T>, owner: Py<PyMontyRepl>) -> Self;
1288
- }
1289
-
1290
- impl FromReplResolveFutures<PySignalTracker<NoLimitTracker>> for EitherFutureSnapshot {
1291
- fn from_repl_resolve_futures(
1292
- state: ReplResolveFutures<PySignalTracker<NoLimitTracker>>,
1293
- owner: Py<PyMontyRepl>,
1294
- ) -> Self {
1295
- Self::ReplNoLimit(state, owner)
1296
- }
1297
- }
1298
-
1299
- impl FromReplResolveFutures<PySignalTracker<LimitedTracker>> for EitherFutureSnapshot {
1300
- fn from_repl_resolve_futures(
1301
- state: ReplResolveFutures<PySignalTracker<LimitedTracker>>,
1302
- owner: Py<PyMontyRepl>,
1303
- ) -> Self {
1304
- Self::ReplLimited(state, owner)
1305
- }
1306
- }
1307
-
1308
- /// Snapshot generated during execution when monty yields to the host to resolve a future.
1309
- ///
1310
- /// Works for both `Monty.start()` and `MontyRepl.feed_start()`.
1311
- #[pyclass(name = "FutureSnapshot", module = "pydantic_monty", frozen)]
1312
- #[derive(Debug)]
1313
- pub struct PyFutureSnapshot {
1314
- snapshot: Mutex<EitherFutureSnapshot>,
1315
- print_callback: Option<Py<PyAny>>,
1316
- dc_registry: DcRegistry,
1317
-
1318
- /// Name of the script being executed
1319
- #[pyo3(get)]
1320
- pub script_name: String,
1321
- }
1322
-
1323
- impl PyFutureSnapshot {
1324
- fn new_py_any<T: ResourceTracker>(
1325
- py: Python<'_>,
1326
- state: ResolveFutures<T>,
1327
- script_name: String,
1328
- print_callback: Option<Py<PyAny>>,
1329
- dc_registry: DcRegistry,
1330
- ) -> PyResult<Bound<'_, PyAny>>
1331
- where
1332
- EitherFutureSnapshot: FromResolveFutures<T>,
1333
- {
1334
- let slf = Self {
1335
- snapshot: Mutex::new(EitherFutureSnapshot::from_resolve_futures(state)),
1336
- print_callback,
1337
- dc_registry,
1338
- script_name,
1339
- };
1340
- slf.into_bound_py_any(py)
1341
- }
1342
-
1343
- /// Constructs a `PyFutureSnapshot` from deserialized parts.
1344
- ///
1345
- /// Used by `load_snapshot` and `load_repl_snapshot` to reconstruct snapshot objects.
1346
- pub(crate) fn from_deserialized(
1347
- py: Python<'_>,
1348
- snapshot: EitherFutureSnapshot,
1349
- print_callback: Option<Py<PyAny>>,
1350
- dc_registry: DcRegistry,
1351
- script_name: String,
1352
- ) -> PyResult<Bound<'_, PyAny>> {
1353
- let slf = Self {
1354
- snapshot: Mutex::new(snapshot),
1355
- print_callback,
1356
- dc_registry,
1357
- script_name,
1358
- };
1359
- slf.into_bound_py_any(py)
1360
- }
1361
-
1362
- /// Creates a `PyFutureSnapshot` for a REPL resolve-futures state.
1363
- fn repl_resolve_futures<T: ResourceTracker>(
1364
- py: Python<'_>,
1365
- state: ReplResolveFutures<T>,
1366
- script_name: String,
1367
- print_callback: Option<Py<PyAny>>,
1368
- dc_registry: DcRegistry,
1369
- repl_owner: Py<PyMontyRepl>,
1370
- ) -> PyResult<Bound<'_, PyAny>>
1371
- where
1372
- EitherFutureSnapshot: FromReplResolveFutures<T>,
1373
- {
1374
- let slf = Self {
1375
- snapshot: Mutex::new(EitherFutureSnapshot::from_repl_resolve_futures(state, repl_owner)),
1376
- print_callback,
1377
- dc_registry,
1378
- script_name,
1379
- };
1380
- slf.into_bound_py_any(py)
1381
- }
1382
- }
1383
-
1384
- #[pymethods]
1385
- impl PyFutureSnapshot {
1386
- /// Resumes execution with results for one or more futures.
1387
- #[pyo3(signature = (results))]
1388
- pub fn resume<'py>(&self, py: Python<'py>, results: &Bound<'_, PyDict>) -> PyResult<Bound<'py, PyAny>> {
1389
- const ARGS_ERROR: &str = "results values must be a dict with either 'return_value' or 'exception', not both";
1390
-
1391
- let mut snapshot = self
1392
- .snapshot
1393
- .lock()
1394
- .map_err(|_| PyRuntimeError::new_err("Snapshot is currently being resumed by another thread"))?;
1395
-
1396
- let snapshot = std::mem::replace(&mut *snapshot, EitherFutureSnapshot::Done);
1397
-
1398
- let external_results = results
1399
- .iter()
1400
- .map(|(key, value)| {
1401
- let call_id = key.extract::<u32>()?;
1402
- let dict = value.cast::<PyDict>()?;
1403
- let value = extract_external_result(py, dict, ARGS_ERROR, &self.dc_registry, call_id)?;
1404
- Ok((call_id, value))
1405
- })
1406
- .collect::<PyResult<Vec<_>>>()?;
1407
-
1408
- // Build print writer before detaching - clone_ref needs py token
1409
- let mut print_cb;
1410
- let print_writer = match &self.print_callback {
1411
- Some(cb) => {
1412
- print_cb = CallbackStringPrint::from_py(cb.clone_ref(py));
1413
- PrintWriter::Callback(&mut print_cb)
1414
- }
1415
- None => PrintWriter::Stdout,
1416
- };
1417
- let mut print_writer = SendWrapper::new(print_writer);
1418
-
1419
- let progress = match snapshot {
1420
- EitherFutureSnapshot::NoLimit(snapshot) => {
1421
- let result = py.detach(|| snapshot.resume(external_results, print_writer.reborrow()));
1422
- EitherProgress::NoLimit(result.map_err(|e| MontyError::new_err(py, e))?)
1423
- }
1424
- EitherFutureSnapshot::Limited(snapshot) => {
1425
- let result = py.detach(|| snapshot.resume(external_results, print_writer.reborrow()));
1426
- EitherProgress::Limited(result.map_err(|e| MontyError::new_err(py, e))?)
1427
- }
1428
- EitherFutureSnapshot::ReplNoLimit(snapshot, owner) => {
1429
- let result = py
1430
- .detach(|| snapshot.resume(external_results, print_writer.reborrow()))
1431
- .map_err(|e| restore_repl_from_repl_start_error(py, &owner, *e))?;
1432
- EitherProgress::ReplNoLimit(result, owner)
1433
- }
1434
- EitherFutureSnapshot::ReplLimited(snapshot, owner) => {
1435
- let result = py
1436
- .detach(|| snapshot.resume(external_results, print_writer.reborrow()))
1437
- .map_err(|e| restore_repl_from_repl_start_error(py, &owner, *e))?;
1438
- EitherProgress::ReplLimited(result, owner)
1439
- }
1440
- EitherFutureSnapshot::Done => return Err(PyRuntimeError::new_err("Progress already resumed")),
1441
- };
1442
-
1443
- // Clone the Arc handle for the next snapshot/complete
1444
- let dc_registry = self.dc_registry.clone_ref(py);
1445
- progress.progress_or_complete(
1446
- py,
1447
- self.script_name.clone(),
1448
- self.print_callback.as_ref().map(|cb| cb.clone_ref(py)),
1449
- dc_registry,
1450
- )
1451
- }
1452
-
1453
- /// Returns the pending call IDs associated with the FutureSnapshot instance.
1454
- ///
1455
- /// # Returns
1456
- /// A slice of pending call IDs.
1457
- #[getter]
1458
- fn pending_call_ids<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyList>> {
1459
- let snapshot = self.snapshot.lock().unwrap_or_else(PoisonError::into_inner);
1460
- match &*snapshot {
1461
- EitherFutureSnapshot::NoLimit(snapshot) => PyList::new(py, snapshot.pending_call_ids()),
1462
- EitherFutureSnapshot::Limited(snapshot) => PyList::new(py, snapshot.pending_call_ids()),
1463
- EitherFutureSnapshot::ReplNoLimit(snapshot, _) => PyList::new(py, snapshot.pending_call_ids()),
1464
- EitherFutureSnapshot::ReplLimited(snapshot, _) => PyList::new(py, snapshot.pending_call_ids()),
1465
- EitherFutureSnapshot::Done => Err(PyRuntimeError::new_err("FutureSnapshot already resumed")),
1466
- }
1467
- }
1468
-
1469
- /// Serializes the FutureSnapshot instance to a binary format.
1470
- ///
1471
- /// The serialized data can be stored and later restored with `load_snapshot()`
1472
- /// or `load_repl_snapshot()`. REPL snapshots automatically include the REPL state.
1473
- ///
1474
- /// Note: The `print_callback` is not serialized and must be re-provided when loading.
1475
- ///
1476
- /// # Returns
1477
- /// Bytes containing the serialized FutureSnapshot instance.
1478
- ///
1479
- /// # Raises
1480
- /// `ValueError` if serialization fails.
1481
- /// `RuntimeError` if the progress has already been resumed.
1482
- fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
1483
- let bytes = crate::serialization::dump_future_snapshot(&self.snapshot, &self.script_name)?;
1484
- Ok(PyBytes::new(py, &bytes))
1485
- }
1486
-
1487
- fn __repr__(&self) -> String {
1488
- let snapshot = self.snapshot.lock().unwrap_or_else(PoisonError::into_inner);
1489
- let pending_call_ids = match &*snapshot {
1490
- EitherFutureSnapshot::NoLimit(s) => s.pending_call_ids(),
1491
- EitherFutureSnapshot::Limited(s) => s.pending_call_ids(),
1492
- EitherFutureSnapshot::ReplNoLimit(s, _) => s.pending_call_ids(),
1493
- EitherFutureSnapshot::ReplLimited(s, _) => s.pending_call_ids(),
1494
- EitherFutureSnapshot::Done => &[],
1495
- };
1496
- format!(
1497
- "FutureSnapshot(script_name='{}', pending_call_ids={pending_call_ids:?})",
1498
- self.script_name,
1499
- )
1500
- }
1501
- }
1502
-
1503
- #[pyclass(name = "MontyComplete", module = "pydantic_monty", frozen)]
1504
- pub struct PyMontyComplete {
1505
- #[pyo3(get)]
1506
- pub output: Py<PyAny>,
1507
- // TODO we might want to add stats on execution here like time, allocations, etc.
1508
- }
1509
-
1510
- impl PyMontyComplete {
1511
- fn create<'py>(py: Python<'py>, output: &MontyObject, dc_registry: &DcRegistry) -> PyResult<Bound<'py, PyAny>> {
1512
- let output = monty_to_py(py, output, dc_registry)?;
1513
- let slf = Self { output };
1514
- slf.into_bound_py_any(py)
1515
- }
1516
- }
1517
-
1518
- #[pymethods]
1519
- impl PyMontyComplete {
1520
- fn __repr__(&self, py: Python<'_>) -> PyResult<String> {
1521
- Ok(format!("MontyComplete(output={})", self.output.bind(py).repr()?))
1522
- }
1523
- }
1524
-
1525
- fn list_str(arg: Option<&Bound<'_, PyList>>, name: &str) -> PyResult<Vec<String>> {
1526
- if let Some(names) = arg {
1527
- names
1528
- .iter()
1529
- .map(|item| item.extract::<String>())
1530
- .collect::<PyResult<Vec<_>>>()
1531
- .map_err(|e| PyTypeError::new_err(format!("{name}: {e}")))
1532
- } else {
1533
- Ok(vec![])
1534
- }
1535
- }
1536
-
1537
- /// A `PrintWriter` implementation that calls a Python callback for each print output.
1538
- ///
1539
- /// This struct holds a GIL-independent `Py<PyAny>` reference to the callback,
1540
- /// allowing it to be used across GIL release boundaries. The GIL is re-acquired
1541
- /// briefly for each callback invocation.
1542
- #[derive(Debug)]
1543
- pub(crate) struct CallbackStringPrint(Py<PyAny>);
1544
-
1545
- impl CallbackStringPrint {
1546
- /// Creates a new `CallbackStringPrint` from a borrowed Python callback.
1547
- fn new(callback: &Bound<'_, PyAny>) -> Self {
1548
- Self(callback.clone().unbind())
1549
- }
1550
-
1551
- /// Creates a new `CallbackStringPrint` from an owned `Py<PyAny>`.
1552
- pub(crate) fn from_py(callback: Py<PyAny>) -> Self {
1553
- Self(callback)
1554
- }
1555
- }
1556
-
1557
- impl PrintWriterCallback for CallbackStringPrint {
1558
- fn stdout_write(&mut self, output: Cow<'_, str>) -> Result<(), MontyException> {
1559
- Python::attach(|py| {
1560
- self.0.bind(py).call1(("stdout", output.as_ref()))?;
1561
- Ok::<_, PyErr>(())
1562
- })
1563
- .map_err(|e| Python::attach(|py| exc_py_to_monty(py, &e)))
1564
- }
1565
-
1566
- fn stdout_push(&mut self, end: char) -> Result<(), MontyException> {
1567
- Python::attach(|py| {
1568
- self.0.bind(py).call1(("stdout", end.to_string()))?;
1569
- Ok::<_, PyErr>(())
1570
- })
1571
- .map_err(|e| Python::attach(|py| exc_py_to_monty(py, &e)))
1572
- }
1573
- }
1574
-
1575
- /// Recursively checks whether a `MontyObject` contains a dataclass, including
1576
- /// inside containers like `List`, `Tuple`, and `Dict`.
1577
- ///
1578
- /// This is used to decide whether to take the iterative execution path: dataclass
1579
- /// method calls need host dispatch, so if any input (even nested) is a dataclass
1580
- /// we must use the iterative runner rather than the non-iterative `run()`.
1581
- fn contains_dataclass(obj: &MontyObject) -> bool {
1582
- match obj {
1583
- MontyObject::Dataclass { .. } => true,
1584
- MontyObject::List(items) | MontyObject::Tuple(items) => items.iter().any(contains_dataclass),
1585
- MontyObject::Dict(pairs) => pairs
1586
- .into_iter()
1587
- .any(|(k, v)| contains_dataclass(k) || contains_dataclass(v)),
1588
- _ => false,
1589
- }
1590
- }
1591
-
1592
- /// Serialization wrapper for `PyMonty` that includes all fields needed for reconstruction.
1593
- #[derive(serde::Serialize, serde::Deserialize)]
1594
- struct SerializedMonty {
1595
- runner: MontyRun,
1596
- script_name: String,
1597
- input_names: Vec<String>,
1598
- }
1599
-
1600
- /// Extract an external result (object or exception) from a dictionary.
1601
- ///
1602
- /// Any dataclass return values are automatically registered in the `dc_registry` via `py_to_monty`
1603
- /// so they can be properly reconstructed on output.
1604
- /// Extracts an `ExternalResult` from a Python dict with a single key.
1605
- ///
1606
- /// Accepts `return_value`, `exception`, or `future` (with value `...`).
1607
- /// The `call_id` is required for `future` results to track the pending call.
1608
- fn extract_external_result(
1609
- py: Python<'_>,
1610
- dict: &Bound<'_, PyDict>,
1611
- error_msg: &'static str,
1612
- dc_registry: &DcRegistry,
1613
- call_id: u32,
1614
- ) -> PyResult<ExtFunctionResult> {
1615
- if dict.len() != 1 {
1616
- Err(PyTypeError::new_err(error_msg))
1617
- } else if let Some(rv) = dict.get_item(intern!(py, "return_value"))? {
1618
- // Return value provided
1619
- Ok(py_to_monty(&rv, dc_registry)?.into())
1620
- } else if let Some(exc) = dict.get_item(intern!(py, "exception"))? {
1621
- // Exception provided
1622
- let py_err = PyErr::from_value(exc.into_any());
1623
- Ok(exc_py_to_monty(py, &py_err).into())
1624
- } else if let Some(exc) = dict.get_item(intern!(py, "future"))? {
1625
- if exc.eq(py.Ellipsis()).unwrap_or_default() {
1626
- Ok(ExtFunctionResult::Future(call_id))
1627
- } else {
1628
- Err(PyTypeError::new_err(
1629
- "Value for the 'future' key must be Ellipsis (...)",
1630
- ))
1631
- }
1632
- } else {
1633
- // wrong key in kwargs
1634
- Err(PyTypeError::new_err(error_msg))
1635
- }
1636
- }
1637
-
1638
- /// Extracts the REPL from a `ReplStartError`, restores it into the owner,
1639
- /// and returns the Python exception.
1640
- fn restore_repl_from_repl_start_error<T: ResourceTracker>(
1641
- py: Python<'_>,
1642
- repl_owner: &Py<PyMontyRepl>,
1643
- err: ReplStartError<T>,
1644
- ) -> PyErr
1645
- where
1646
- EitherRepl: FromCoreRepl<T>,
1647
- {
1648
- repl_owner.get().put_repl(EitherRepl::from_core(err.repl));
1649
- MontyError::new_err(py, err.error)
1650
- }