superacli 1.1.6 → 1.1.8

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 (1268) hide show
  1. package/CONTRIBUTING.md +270 -0
  2. package/README.md +141 -54
  3. package/__tests__/adapter-schema.test.js +251 -86
  4. package/__tests__/azd-plugin.test.js +109 -0
  5. package/__tests__/config.test.js +4 -3
  6. package/__tests__/discover.test.js +59 -0
  7. package/__tests__/goose-plugin.test.js +149 -0
  8. package/__tests__/help-json.test.js +2 -0
  9. package/__tests__/openhands-plugin.test.js +106 -0
  10. package/__tests__/plugin-cocoindex-code-uninstall.test.js +19 -0
  11. package/__tests__/plugin-cocoindex-code.test.js +37 -0
  12. package/__tests__/plugin-install-guidance.test.js +81 -0
  13. package/__tests__/plugins-registry.test.js +44 -0
  14. package/__tests__/plugins-store.test.js +40 -5
  15. package/__tests__/process-adapter.test.js +50 -1
  16. package/__tests__/resend-plugin.test.js +109 -82
  17. package/__tests__/server-app.test.js +1 -0
  18. package/__tests__/server-routes-commands.test.js +20 -2
  19. package/__tests__/server-routes-plugins.test.js +130 -0
  20. package/__tests__/skills.test.js +26 -0
  21. package/__tests__/squirrelscan-plugin.test.js +129 -0
  22. package/__tests__/uipath-plugin.test.js +104 -0
  23. package/__tests__/uipathcli-plugin.test.js +95 -0
  24. package/cli/adapters/mcp.js +2 -0
  25. package/cli/adapters/process.js +50 -7
  26. package/cli/config.js +240 -3
  27. package/cli/discover.js +157 -0
  28. package/cli/help-json.js +16 -1
  29. package/cli/plugin-install-guidance.js +92 -37
  30. package/cli/plugins-manager.js +4 -3
  31. package/cli/plugins-registry.js +74 -8
  32. package/cli/plugins-store.js +78 -17
  33. package/cli/skills-mcp.js +1 -1
  34. package/cli/skills.js +39 -2
  35. package/cli/supercli.js +255 -63
  36. package/docs/feature-gaps.md +8 -8
  37. package/docs/features/azd-uipath-plugins.md +43 -0
  38. package/docs/features/server-plugins.md +62 -0
  39. package/docs/features/skills.md +9 -5
  40. package/docs/index.html +183 -123
  41. package/docs/{supported-harnesses.md → plugins-available.md} +4 -3
  42. package/docs/{plugin-harness-guide.md → plugins-how-to.md} +1 -1
  43. package/docs/plugins.md +26 -20
  44. package/docs/server-plugins-usage-guide.md +182 -0
  45. package/docs/skills-catalog.md +12 -10
  46. package/index.html +384 -0
  47. package/package.json +2 -2
  48. package/plugins/agent-browser/README.md +69 -0
  49. package/plugins/agent-browser/plugin.json +111 -0
  50. package/plugins/agent-browser/skills/quickstart/SKILL.md +66 -0
  51. package/plugins/aider/README.md +53 -0
  52. package/plugins/aider/plugin.json +105 -0
  53. package/plugins/aider/scripts/aider-wrapper.js +243 -0
  54. package/plugins/aider/scripts/setup-aider.js +37 -0
  55. package/plugins/aider/skills/dry-run-review.md +24 -0
  56. package/plugins/aider/skills/model-and-provider.md +24 -0
  57. package/plugins/aider/skills/one-shot-edits.md +30 -0
  58. package/plugins/aider/skills/quickstart/SKILL.md +51 -0
  59. package/plugins/azd/README.md +28 -0
  60. package/plugins/azd/plugin.json +87 -0
  61. package/plugins/azd/skills/quickstart/SKILL.md +41 -0
  62. package/plugins/blogwatcher/README.md +3 -3
  63. package/plugins/boxlite/Dockerfile +9 -0
  64. package/plugins/boxlite/README.md +62 -0
  65. package/plugins/boxlite/plugin.json +201 -0
  66. package/plugins/boxlite/scripts/run-boxlite.js +106 -0
  67. package/plugins/boxlite/skills/quickstart/SKILL.md +40 -0
  68. package/plugins/cass/plugin.json +150 -0
  69. package/plugins/cass/scripts/setup-cass.js +47 -0
  70. package/plugins/cass/skills/quickstart/SKILL.md +46 -0
  71. package/plugins/clever/README.md +46 -0
  72. package/plugins/clever/plugin.json +119 -0
  73. package/plugins/clever/scripts/setup-clever.js +28 -0
  74. package/plugins/clever/skills/auth-and-profile.md +29 -0
  75. package/plugins/clever/skills/passthrough-safety.md +21 -0
  76. package/plugins/clever/skills/quickstart/SKILL.md +45 -0
  77. package/plugins/clever/skills/resource-inventory.md +24 -0
  78. package/plugins/clix/README.md +4 -4
  79. package/plugins/cocoindex-code/README.md +64 -0
  80. package/plugins/cocoindex-code/plugin.json +81 -0
  81. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-310.pyc +0 -0
  82. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-311.pyc +0 -0
  83. package/plugins/cocoindex-code/scripts/post-install.js +61 -0
  84. package/plugins/cocoindex-code/scripts/post-uninstall.js +25 -0
  85. package/plugins/cocoindex-code/scripts/query.py +88 -0
  86. package/plugins/cocoindex-code/scripts/run-query.js +50 -0
  87. package/plugins/cocoindex-code/skills/quickstart/SKILL.md +73 -0
  88. package/plugins/copilot/README.md +24 -0
  89. package/plugins/copilot/plugin.json +80 -0
  90. package/plugins/copilot/skills/quickstart/SKILL.md +44 -0
  91. package/plugins/gemini/README.md +24 -0
  92. package/plugins/gemini/plugin.json +98 -0
  93. package/plugins/gemini/skills/quickstart/SKILL.md +44 -0
  94. package/plugins/gifcap/plugin.json +119 -0
  95. package/plugins/gifcap/scripts/setup-gifcap.js +44 -0
  96. package/plugins/gifcap/skills/quickstart/SKILL.md +34 -0
  97. package/plugins/gifcap/test-record-quiet.gif +0 -0
  98. package/plugins/gifcap/test-record.gif +0 -0
  99. package/plugins/goose/README.md +36 -0
  100. package/plugins/goose/plugin.json +183 -0
  101. package/plugins/goose/skills/quickstart/SKILL.md +44 -0
  102. package/plugins/json-server/README.md +58 -0
  103. package/plugins/json-server/plugin.json +113 -0
  104. package/plugins/json-server/skills/quickstart/SKILL.md +57 -0
  105. package/plugins/lightpanda/README.md +145 -0
  106. package/plugins/lightpanda/package-lock.json +1375 -0
  107. package/plugins/lightpanda/package.json +12 -0
  108. package/plugins/lightpanda/plugin.json +116 -0
  109. package/plugins/lightpanda/scripts/lightpanda-contacts.js +494 -0
  110. package/plugins/lightpanda/scripts/lightpanda-generic-extract.js +403 -0
  111. package/plugins/lightpanda/scripts/lightpanda-wrapper.js +480 -0
  112. package/plugins/lightpanda/scripts/setup-lightpanda.js +39 -0
  113. package/plugins/lightpanda/skills/contact-discovery.md +51 -0
  114. package/plugins/lightpanda/skills/generic-extraction.md +66 -0
  115. package/plugins/lightpanda/skills/quickstart/SKILL.md +103 -0
  116. package/plugins/lightpanda/skills/resilient-navigation.md +42 -0
  117. package/plugins/monty/README.md +2 -2
  118. package/plugins/nullclaw/README.md +3 -3
  119. package/plugins/offline-ai/README.md +23 -0
  120. package/plugins/offline-ai/plugin.json +82 -0
  121. package/plugins/offline-ai/skills/quickstart/SKILL.md +43 -0
  122. package/plugins/openhands/README.md +25 -0
  123. package/plugins/openhands/plugin.json +116 -0
  124. package/plugins/openhands/skills/quickstart/SKILL.md +26 -0
  125. package/plugins/plandex/README.md +25 -0
  126. package/plugins/plandex/plugin.json +130 -0
  127. package/plugins/plandex/skills/quickstart/SKILL.md +50 -0
  128. package/plugins/plugins.json +199 -0
  129. package/plugins/squirrelscan/Dockerfile +5 -0
  130. package/plugins/squirrelscan/README.md +47 -0
  131. package/plugins/squirrelscan/plugin.json +493 -0
  132. package/plugins/squirrelscan/scripts/post-install.js +33 -0
  133. package/plugins/squirrelscan/scripts/post-uninstall.js +25 -0
  134. package/plugins/squirrelscan/scripts/run-squirrel.js +73 -0
  135. package/plugins/squirrelscan/skills/audit-workflow/SKILL.md +33 -0
  136. package/plugins/squirrelscan/skills/publish-report/SKILL.md +33 -0
  137. package/plugins/squirrelscan/skills/quickstart/SKILL.md +41 -0
  138. package/plugins/uipath/README.md +27 -0
  139. package/plugins/uipath/plugin.json +86 -0
  140. package/plugins/uipath/skills/quickstart/SKILL.md +47 -0
  141. package/plugins/uipathcli/README.md +28 -0
  142. package/plugins/uipathcli/plugin.json +120 -0
  143. package/plugins/uipathcli/scripts/run-uipath-cli.js +49 -0
  144. package/plugins/uipathcli/skills/quickstart/SKILL.md +22 -0
  145. package/plugins/xurl/README.md +4 -4
  146. package/server/app.js +5 -2
  147. package/server/public/app.js +3 -0
  148. package/server/routes/commands.js +95 -12
  149. package/server/routes/plugins.js +262 -0
  150. package/server/services/pluginsService.js +303 -0
  151. package/server/views/command-edit.ejs +196 -14
  152. package/server/views/partials/head.ejs +1 -0
  153. package/server/views/plugins.ejs +264 -0
  154. package/tests/test-plugins-registry.js +30 -0
  155. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl +0 -20
  156. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl.meta.json +0 -1
  157. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl +0 -21
  158. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl.meta.json +0 -1
  159. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl +0 -22
  160. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl.meta.json +0 -1
  161. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl +0 -23
  162. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl.meta.json +0 -1
  163. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl +0 -24
  164. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl.meta.json +0 -1
  165. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl +0 -24
  166. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl.meta.json +0 -1
  167. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl +0 -24
  168. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl.meta.json +0 -1
  169. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl +0 -24
  170. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl.meta.json +0 -1
  171. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl +0 -24
  172. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl.meta.json +0 -1
  173. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl +0 -24
  174. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl.meta.json +0 -1
  175. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl +0 -24
  176. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl.meta.json +0 -1
  177. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl +0 -24
  178. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl.meta.json +0 -1
  179. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl +0 -24
  180. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl.meta.json +0 -1
  181. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl +0 -25
  182. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl.meta.json +0 -1
  183. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl +0 -25
  184. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl.meta.json +0 -1
  185. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl +0 -25
  186. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl.meta.json +0 -1
  187. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl +0 -26
  188. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl.meta.json +0 -1
  189. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl +0 -27
  190. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl.meta.json +0 -1
  191. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl +0 -28
  192. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl.meta.json +0 -1
  193. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl +0 -29
  194. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl.meta.json +0 -1
  195. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl +0 -30
  196. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl.meta.json +0 -1
  197. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl +0 -31
  198. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl.meta.json +0 -1
  199. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl +0 -32
  200. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl.meta.json +0 -1
  201. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl +0 -32
  202. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl.meta.json +0 -1
  203. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl +0 -32
  204. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl.meta.json +0 -1
  205. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl +0 -32
  206. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl.meta.json +0 -1
  207. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl +0 -32
  208. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl.meta.json +0 -1
  209. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl +0 -32
  210. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl.meta.json +0 -1
  211. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl +0 -32
  212. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl.meta.json +0 -1
  213. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl +0 -32
  214. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl.meta.json +0 -1
  215. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl +0 -32
  216. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl.meta.json +0 -1
  217. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl +0 -32
  218. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl.meta.json +0 -1
  219. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl +0 -32
  220. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl.meta.json +0 -1
  221. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl +0 -32
  222. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl.meta.json +0 -1
  223. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl +0 -32
  224. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl.meta.json +0 -1
  225. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl +0 -32
  226. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl.meta.json +0 -1
  227. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl +0 -33
  228. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl.meta.json +0 -1
  229. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl +0 -33
  230. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl.meta.json +0 -1
  231. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl +0 -34
  232. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl.meta.json +0 -1
  233. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl +0 -34
  234. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl.meta.json +0 -1
  235. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl +0 -35
  236. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl.meta.json +0 -1
  237. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl +0 -36
  238. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl.meta.json +0 -1
  239. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl +0 -37
  240. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl.meta.json +0 -1
  241. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl +0 -38
  242. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl.meta.json +0 -1
  243. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl +0 -39
  244. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl.meta.json +0 -1
  245. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl +0 -40
  246. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl.meta.json +0 -1
  247. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl +0 -41
  248. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl.meta.json +0 -1
  249. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl +0 -42
  250. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl.meta.json +0 -1
  251. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl +0 -43
  252. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl.meta.json +0 -1
  253. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl +0 -44
  254. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl.meta.json +0 -1
  255. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl +0 -45
  256. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl.meta.json +0 -1
  257. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl +0 -46
  258. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl.meta.json +0 -1
  259. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl +0 -47
  260. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl.meta.json +0 -1
  261. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl +0 -48
  262. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl.meta.json +0 -1
  263. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl +0 -49
  264. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl.meta.json +0 -1
  265. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl +0 -50
  266. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl.meta.json +0 -1
  267. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl +0 -51
  268. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl.meta.json +0 -1
  269. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl +0 -52
  270. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl.meta.json +0 -1
  271. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl +0 -53
  272. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl.meta.json +0 -1
  273. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl +0 -54
  274. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl.meta.json +0 -1
  275. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl +0 -55
  276. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl.meta.json +0 -1
  277. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl +0 -56
  278. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl.meta.json +0 -1
  279. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl +0 -57
  280. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl.meta.json +0 -1
  281. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl +0 -57
  282. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl.meta.json +0 -1
  283. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl +0 -57
  284. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl.meta.json +0 -1
  285. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl +0 -57
  286. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl.meta.json +0 -1
  287. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl +0 -57
  288. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl.meta.json +0 -1
  289. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl +0 -57
  290. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl.meta.json +0 -1
  291. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl +0 -57
  292. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl.meta.json +0 -1
  293. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl +0 -57
  294. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl.meta.json +0 -1
  295. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl +0 -57
  296. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl.meta.json +0 -1
  297. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl +0 -57
  298. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl.meta.json +0 -1
  299. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl +0 -57
  300. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl.meta.json +0 -1
  301. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl +0 -57
  302. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl.meta.json +0 -1
  303. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl +0 -57
  304. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl.meta.json +0 -1
  305. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl +0 -57
  306. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl.meta.json +0 -1
  307. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl +0 -57
  308. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl.meta.json +0 -1
  309. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl +0 -57
  310. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl.meta.json +0 -1
  311. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl +0 -57
  312. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl.meta.json +0 -1
  313. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl +0 -57
  314. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl.meta.json +0 -1
  315. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl +0 -57
  316. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl.meta.json +0 -1
  317. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl +0 -57
  318. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl.meta.json +0 -1
  319. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl +0 -57
  320. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl.meta.json +0 -1
  321. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl +0 -57
  322. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl.meta.json +0 -1
  323. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl +0 -57
  324. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl.meta.json +0 -1
  325. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl +0 -57
  326. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl.meta.json +0 -1
  327. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl +0 -57
  328. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl.meta.json +0 -1
  329. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl +0 -57
  330. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl.meta.json +0 -1
  331. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl +0 -57
  332. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl.meta.json +0 -1
  333. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl +0 -57
  334. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl.meta.json +0 -1
  335. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl +0 -57
  336. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl.meta.json +0 -1
  337. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl +0 -57
  338. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl.meta.json +0 -1
  339. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl +0 -58
  340. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl.meta.json +0 -1
  341. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl +0 -59
  342. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl.meta.json +0 -1
  343. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl +0 -60
  344. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl.meta.json +0 -1
  345. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl +0 -60
  346. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl.meta.json +0 -1
  347. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl +0 -60
  348. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl.meta.json +0 -1
  349. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl +0 -60
  350. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl.meta.json +0 -1
  351. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl +0 -60
  352. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl.meta.json +0 -1
  353. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl +0 -60
  354. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl.meta.json +0 -1
  355. package/.beads/config.yaml +0 -4
  356. package/.beads/issues.jsonl +0 -60
  357. package/.beads/metadata.json +0 -4
  358. package/docs/docs.html +0 -224
  359. package/docs/mcp-cheatsheet.md +0 -324
  360. package/docs/visual-overview.md +0 -21
  361. package/ref-monty/.cargo/config.toml +0 -3
  362. package/ref-monty/.claude/settings.json +0 -60
  363. package/ref-monty/.claude/skills/fastmod/SKILL.md +0 -22
  364. package/ref-monty/.claude/skills/python-playground/SKILL.md +0 -47
  365. package/ref-monty/.codecov.yml +0 -12
  366. package/ref-monty/.github/actions/build-pgo-wheel/action.yml +0 -72
  367. package/ref-monty/.github/workflows/ci.yml +0 -776
  368. package/ref-monty/.github/workflows/codspeed.yml +0 -45
  369. package/ref-monty/.github/workflows/init-npm-packages.yml +0 -82
  370. package/ref-monty/.pre-commit-config.yaml +0 -47
  371. package/ref-monty/.python-version +0 -1
  372. package/ref-monty/.rustfmt.toml +0 -4
  373. package/ref-monty/.zed/settings.json +0 -11
  374. package/ref-monty/CLAUDE.md +0 -535
  375. package/ref-monty/Cargo.lock +0 -3798
  376. package/ref-monty/Cargo.toml +0 -87
  377. package/ref-monty/LICENSE +0 -21
  378. package/ref-monty/Makefile +0 -216
  379. package/ref-monty/README.md +0 -430
  380. package/ref-monty/RELEASING.md +0 -47
  381. package/ref-monty/crates/fuzz/Cargo.toml +0 -30
  382. package/ref-monty/crates/fuzz/fuzz_targets/string_input_panic.rs +0 -37
  383. package/ref-monty/crates/fuzz/fuzz_targets/tokens_input_panic.rs +0 -552
  384. package/ref-monty/crates/monty/Cargo.toml +0 -68
  385. package/ref-monty/crates/monty/benches/main.rs +0 -247
  386. package/ref-monty/crates/monty/build.rs +0 -10
  387. package/ref-monty/crates/monty/src/args.rs +0 -733
  388. package/ref-monty/crates/monty/src/asyncio.rs +0 -179
  389. package/ref-monty/crates/monty/src/builtins/abs.rs +0 -55
  390. package/ref-monty/crates/monty/src/builtins/all.rs +0 -30
  391. package/ref-monty/crates/monty/src/builtins/any.rs +0 -30
  392. package/ref-monty/crates/monty/src/builtins/bin.rs +0 -59
  393. package/ref-monty/crates/monty/src/builtins/chr.rs +0 -46
  394. package/ref-monty/crates/monty/src/builtins/divmod.rs +0 -164
  395. package/ref-monty/crates/monty/src/builtins/enumerate.rs +0 -52
  396. package/ref-monty/crates/monty/src/builtins/filter.rs +0 -67
  397. package/ref-monty/crates/monty/src/builtins/getattr.rs +0 -65
  398. package/ref-monty/crates/monty/src/builtins/hash.rs +0 -28
  399. package/ref-monty/crates/monty/src/builtins/hex.rs +0 -58
  400. package/ref-monty/crates/monty/src/builtins/id.rs +0 -24
  401. package/ref-monty/crates/monty/src/builtins/isinstance.rs +0 -68
  402. package/ref-monty/crates/monty/src/builtins/len.rs +0 -25
  403. package/ref-monty/crates/monty/src/builtins/map.rs +0 -98
  404. package/ref-monty/crates/monty/src/builtins/min_max.rs +0 -113
  405. package/ref-monty/crates/monty/src/builtins/mod.rs +0 -246
  406. package/ref-monty/crates/monty/src/builtins/next.rs +0 -21
  407. package/ref-monty/crates/monty/src/builtins/oct.rs +0 -59
  408. package/ref-monty/crates/monty/src/builtins/ord.rs +0 -67
  409. package/ref-monty/crates/monty/src/builtins/pow.rs +0 -365
  410. package/ref-monty/crates/monty/src/builtins/print.rs +0 -141
  411. package/ref-monty/crates/monty/src/builtins/repr.rs +0 -16
  412. package/ref-monty/crates/monty/src/builtins/reversed.rs +0 -28
  413. package/ref-monty/crates/monty/src/builtins/round.rs +0 -174
  414. package/ref-monty/crates/monty/src/builtins/sorted.rs +0 -151
  415. package/ref-monty/crates/monty/src/builtins/sum.rs +0 -66
  416. package/ref-monty/crates/monty/src/builtins/type_.rs +0 -16
  417. package/ref-monty/crates/monty/src/builtins/zip.rs +0 -77
  418. package/ref-monty/crates/monty/src/bytecode/builder.rs +0 -699
  419. package/ref-monty/crates/monty/src/bytecode/code.rs +0 -310
  420. package/ref-monty/crates/monty/src/bytecode/compiler.rs +0 -3206
  421. package/ref-monty/crates/monty/src/bytecode/mod.rs +0 -24
  422. package/ref-monty/crates/monty/src/bytecode/op.rs +0 -617
  423. package/ref-monty/crates/monty/src/bytecode/vm/async_exec.rs +0 -1058
  424. package/ref-monty/crates/monty/src/bytecode/vm/attr.rs +0 -63
  425. package/ref-monty/crates/monty/src/bytecode/vm/binary.rs +0 -487
  426. package/ref-monty/crates/monty/src/bytecode/vm/call.rs +0 -767
  427. package/ref-monty/crates/monty/src/bytecode/vm/collections.rs +0 -741
  428. package/ref-monty/crates/monty/src/bytecode/vm/compare.rs +0 -147
  429. package/ref-monty/crates/monty/src/bytecode/vm/exceptions.rs +0 -297
  430. package/ref-monty/crates/monty/src/bytecode/vm/format.rs +0 -132
  431. package/ref-monty/crates/monty/src/bytecode/vm/mod.rs +0 -1958
  432. package/ref-monty/crates/monty/src/bytecode/vm/scheduler.rs +0 -620
  433. package/ref-monty/crates/monty/src/exception_private.rs +0 -1513
  434. package/ref-monty/crates/monty/src/exception_public.rs +0 -346
  435. package/ref-monty/crates/monty/src/expressions.rs +0 -694
  436. package/ref-monty/crates/monty/src/fstring.rs +0 -854
  437. package/ref-monty/crates/monty/src/function.rs +0 -119
  438. package/ref-monty/crates/monty/src/heap.rs +0 -1073
  439. package/ref-monty/crates/monty/src/heap_data.rs +0 -985
  440. package/ref-monty/crates/monty/src/heap_traits.rs +0 -312
  441. package/ref-monty/crates/monty/src/intern.rs +0 -837
  442. package/ref-monty/crates/monty/src/io.rs +0 -106
  443. package/ref-monty/crates/monty/src/lib.rs +0 -52
  444. package/ref-monty/crates/monty/src/modules/asyncio.rs +0 -144
  445. package/ref-monty/crates/monty/src/modules/math.rs +0 -1453
  446. package/ref-monty/crates/monty/src/modules/mod.rs +0 -120
  447. package/ref-monty/crates/monty/src/modules/os.rs +0 -116
  448. package/ref-monty/crates/monty/src/modules/pathlib.rs +0 -33
  449. package/ref-monty/crates/monty/src/modules/re.rs +0 -606
  450. package/ref-monty/crates/monty/src/modules/sys.rs +0 -60
  451. package/ref-monty/crates/monty/src/modules/typing.rs +0 -70
  452. package/ref-monty/crates/monty/src/namespace.rs +0 -21
  453. package/ref-monty/crates/monty/src/object.rs +0 -1040
  454. package/ref-monty/crates/monty/src/os.rs +0 -215
  455. package/ref-monty/crates/monty/src/parse.rs +0 -1730
  456. package/ref-monty/crates/monty/src/prepare.rs +0 -3015
  457. package/ref-monty/crates/monty/src/repl.rs +0 -1109
  458. package/ref-monty/crates/monty/src/resource.rs +0 -559
  459. package/ref-monty/crates/monty/src/run.rs +0 -457
  460. package/ref-monty/crates/monty/src/run_progress.rs +0 -821
  461. package/ref-monty/crates/monty/src/signature.rs +0 -651
  462. package/ref-monty/crates/monty/src/sorting.rs +0 -100
  463. package/ref-monty/crates/monty/src/types/bytes.rs +0 -2356
  464. package/ref-monty/crates/monty/src/types/dataclass.rs +0 -345
  465. package/ref-monty/crates/monty/src/types/dict.rs +0 -879
  466. package/ref-monty/crates/monty/src/types/dict_view.rs +0 -619
  467. package/ref-monty/crates/monty/src/types/iter.rs +0 -799
  468. package/ref-monty/crates/monty/src/types/list.rs +0 -929
  469. package/ref-monty/crates/monty/src/types/long_int.rs +0 -211
  470. package/ref-monty/crates/monty/src/types/mod.rs +0 -48
  471. package/ref-monty/crates/monty/src/types/module.rs +0 -146
  472. package/ref-monty/crates/monty/src/types/namedtuple.rs +0 -261
  473. package/ref-monty/crates/monty/src/types/path.rs +0 -596
  474. package/ref-monty/crates/monty/src/types/property.rs +0 -35
  475. package/ref-monty/crates/monty/src/types/py_trait.rs +0 -322
  476. package/ref-monty/crates/monty/src/types/range.rs +0 -285
  477. package/ref-monty/crates/monty/src/types/re_match.rs +0 -522
  478. package/ref-monty/crates/monty/src/types/re_pattern.rs +0 -726
  479. package/ref-monty/crates/monty/src/types/set.rs +0 -1373
  480. package/ref-monty/crates/monty/src/types/slice.rs +0 -257
  481. package/ref-monty/crates/monty/src/types/str.rs +0 -2051
  482. package/ref-monty/crates/monty/src/types/tuple.rs +0 -376
  483. package/ref-monty/crates/monty/src/types/type.rs +0 -407
  484. package/ref-monty/crates/monty/src/value.rs +0 -2558
  485. package/ref-monty/crates/monty/test_cases/args__dict_get_no_args.py +0 -3
  486. package/ref-monty/crates/monty/test_cases/args__dict_get_too_many.py +0 -3
  487. package/ref-monty/crates/monty/test_cases/args__dict_items_with_args.py +0 -3
  488. package/ref-monty/crates/monty/test_cases/args__dict_keys_with_args.py +0 -3
  489. package/ref-monty/crates/monty/test_cases/args__dict_pop_no_args.py +0 -3
  490. package/ref-monty/crates/monty/test_cases/args__dict_pop_too_many.py +0 -3
  491. package/ref-monty/crates/monty/test_cases/args__dict_values_with_args.py +0 -3
  492. package/ref-monty/crates/monty/test_cases/args__id_too_many.py +0 -2
  493. package/ref-monty/crates/monty/test_cases/args__len_no_args.py +0 -2
  494. package/ref-monty/crates/monty/test_cases/args__len_too_many.py +0 -2
  495. package/ref-monty/crates/monty/test_cases/args__len_type_error_int.py +0 -9
  496. package/ref-monty/crates/monty/test_cases/args__len_type_error_none.py +0 -9
  497. package/ref-monty/crates/monty/test_cases/args__list_append_no_args.py +0 -3
  498. package/ref-monty/crates/monty/test_cases/args__list_append_too_many.py +0 -3
  499. package/ref-monty/crates/monty/test_cases/args__list_insert_too_few.py +0 -3
  500. package/ref-monty/crates/monty/test_cases/args__list_insert_too_many.py +0 -3
  501. package/ref-monty/crates/monty/test_cases/args__repr_no_args.py +0 -2
  502. package/ref-monty/crates/monty/test_cases/arith__div_zero_float.py +0 -2
  503. package/ref-monty/crates/monty/test_cases/arith__div_zero_int.py +0 -2
  504. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_float.py +0 -2
  505. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_int.py +0 -2
  506. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg.py +0 -2
  507. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg_builtin.py +0 -9
  508. package/ref-monty/crates/monty/test_cases/assert__expr_fail.py +0 -2
  509. package/ref-monty/crates/monty/test_cases/assert__fail.py +0 -2
  510. package/ref-monty/crates/monty/test_cases/assert__fail_msg.py +0 -2
  511. package/ref-monty/crates/monty/test_cases/assert__fn_fail.py +0 -3
  512. package/ref-monty/crates/monty/test_cases/assert__ops.py +0 -11
  513. package/ref-monty/crates/monty/test_cases/async__asyncio_run.py +0 -47
  514. package/ref-monty/crates/monty/test_cases/async__basic.py +0 -10
  515. package/ref-monty/crates/monty/test_cases/async__closure.py +0 -14
  516. package/ref-monty/crates/monty/test_cases/async__double_await_coroutine.py +0 -16
  517. package/ref-monty/crates/monty/test_cases/async__exception.py +0 -10
  518. package/ref-monty/crates/monty/test_cases/async__ext_call.py +0 -73
  519. package/ref-monty/crates/monty/test_cases/async__gather_all.py +0 -85
  520. package/ref-monty/crates/monty/test_cases/async__nested_await.py +0 -15
  521. package/ref-monty/crates/monty/test_cases/async__nested_gather_ext.py +0 -37
  522. package/ref-monty/crates/monty/test_cases/async__not_awaitable.py +0 -10
  523. package/ref-monty/crates/monty/test_cases/async__not_imported.py +0 -14
  524. package/ref-monty/crates/monty/test_cases/async__recursion_depth_isolation.py +0 -27
  525. package/ref-monty/crates/monty/test_cases/async__return_types.py +0 -31
  526. package/ref-monty/crates/monty/test_cases/async__sequential.py +0 -16
  527. package/ref-monty/crates/monty/test_cases/async__traceback.py +0 -19
  528. package/ref-monty/crates/monty/test_cases/async__with_args.py +0 -14
  529. package/ref-monty/crates/monty/test_cases/attr__get_int_error.py +0 -9
  530. package/ref-monty/crates/monty/test_cases/attr__get_list_error.py +0 -9
  531. package/ref-monty/crates/monty/test_cases/attr__set_frozen_nonfield.py +0 -12
  532. package/ref-monty/crates/monty/test_cases/attr__set_int_error.py +0 -10
  533. package/ref-monty/crates/monty/test_cases/attr__set_list_error.py +0 -10
  534. package/ref-monty/crates/monty/test_cases/bench__kitchen_sink.py +0 -68
  535. package/ref-monty/crates/monty/test_cases/bool__ops.py +0 -20
  536. package/ref-monty/crates/monty/test_cases/builtin__add_type_error.py +0 -2
  537. package/ref-monty/crates/monty/test_cases/builtin__filter.py +0 -62
  538. package/ref-monty/crates/monty/test_cases/builtin__filter_not_iterable.py +0 -11
  539. package/ref-monty/crates/monty/test_cases/builtin__getattr.py +0 -84
  540. package/ref-monty/crates/monty/test_cases/builtin__iter_funcs.py +0 -42
  541. package/ref-monty/crates/monty/test_cases/builtin__iter_next.py +0 -66
  542. package/ref-monty/crates/monty/test_cases/builtin__map.py +0 -74
  543. package/ref-monty/crates/monty/test_cases/builtin__map_not_iterable.py +0 -11
  544. package/ref-monty/crates/monty/test_cases/builtin__math_funcs.py +0 -154
  545. package/ref-monty/crates/monty/test_cases/builtin__more_iter_funcs.py +0 -148
  546. package/ref-monty/crates/monty/test_cases/builtin__next_stop_iteration.py +0 -10
  547. package/ref-monty/crates/monty/test_cases/builtin__print_invalid_kwarg.py +0 -9
  548. package/ref-monty/crates/monty/test_cases/builtin__print_kwargs.py +0 -12
  549. package/ref-monty/crates/monty/test_cases/builtin__repr.py +0 -3
  550. package/ref-monty/crates/monty/test_cases/builtin__string_funcs.py +0 -73
  551. package/ref-monty/crates/monty/test_cases/bytes__decode_invalid_utf8.py +0 -18
  552. package/ref-monty/crates/monty/test_cases/bytes__endswith_str_error.py +0 -10
  553. package/ref-monty/crates/monty/test_cases/bytes__getitem_index_error.py +0 -10
  554. package/ref-monty/crates/monty/test_cases/bytes__index_start_gt_end.py +0 -10
  555. package/ref-monty/crates/monty/test_cases/bytes__methods.py +0 -394
  556. package/ref-monty/crates/monty/test_cases/bytes__negative_count.py +0 -9
  557. package/ref-monty/crates/monty/test_cases/bytes__ops.py +0 -90
  558. package/ref-monty/crates/monty/test_cases/bytes__startswith_str_error.py +0 -10
  559. package/ref-monty/crates/monty/test_cases/call_object.py +0 -3
  560. package/ref-monty/crates/monty/test_cases/chain_comparison__all.py +0 -79
  561. package/ref-monty/crates/monty/test_cases/closure__param_shadows_outer.py +0 -81
  562. package/ref-monty/crates/monty/test_cases/closure__pep448.py +0 -203
  563. package/ref-monty/crates/monty/test_cases/closure__undefined_nonlocal.py +0 -13
  564. package/ref-monty/crates/monty/test_cases/compare__mixed_types.py +0 -120
  565. package/ref-monty/crates/monty/test_cases/comprehension__all.py +0 -208
  566. package/ref-monty/crates/monty/test_cases/comprehension__scope.py +0 -7
  567. package/ref-monty/crates/monty/test_cases/comprehension__unbound_local.py +0 -14
  568. package/ref-monty/crates/monty/test_cases/dataclass__basic.py +0 -238
  569. package/ref-monty/crates/monty/test_cases/dataclass__call_field_error.py +0 -12
  570. package/ref-monty/crates/monty/test_cases/dataclass__frozen_set_error.py +0 -12
  571. package/ref-monty/crates/monty/test_cases/dataclass__get_missing_attr_error.py +0 -11
  572. package/ref-monty/crates/monty/test_cases/dict__get_unhashable_key.py +0 -3
  573. package/ref-monty/crates/monty/test_cases/dict__literal_unhashable_key.py +0 -2
  574. package/ref-monty/crates/monty/test_cases/dict__method_pop_missing_error.py +0 -3
  575. package/ref-monty/crates/monty/test_cases/dict__methods.py +0 -151
  576. package/ref-monty/crates/monty/test_cases/dict__ops.py +0 -133
  577. package/ref-monty/crates/monty/test_cases/dict__pop_unhashable_key.py +0 -4
  578. package/ref-monty/crates/monty/test_cases/dict__popitem_empty.py +0 -9
  579. package/ref-monty/crates/monty/test_cases/dict__subscript_missing_key.py +0 -3
  580. package/ref-monty/crates/monty/test_cases/dict__unhashable_dict_key.py +0 -2
  581. package/ref-monty/crates/monty/test_cases/dict__unhashable_list_key.py +0 -2
  582. package/ref-monty/crates/monty/test_cases/dict__unpack_type_error.py +0 -2
  583. package/ref-monty/crates/monty/test_cases/dict__views.py +0 -165
  584. package/ref-monty/crates/monty/test_cases/edge__all.py +0 -26
  585. package/ref-monty/crates/monty/test_cases/edge__float_int_mod.py +0 -2
  586. package/ref-monty/crates/monty/test_cases/edge__int_float_mod.py +0 -2
  587. package/ref-monty/crates/monty/test_cases/exc__args.py +0 -16
  588. package/ref-monty/crates/monty/test_cases/exc__str.py +0 -15
  589. package/ref-monty/crates/monty/test_cases/execute_ok__all.py +0 -54
  590. package/ref-monty/crates/monty/test_cases/execute_raise__error_instance_str.py +0 -2
  591. package/ref-monty/crates/monty/test_cases/execute_raise__error_no_args.py +0 -2
  592. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg.py +0 -2
  593. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg_quotes.py +0 -2
  594. package/ref-monty/crates/monty/test_cases/execute_raise__error_type.py +0 -2
  595. package/ref-monty/crates/monty/test_cases/execute_raise__raise_instance_via_var.py +0 -4
  596. package/ref-monty/crates/monty/test_cases/execute_raise__raise_list.py +0 -2
  597. package/ref-monty/crates/monty/test_cases/execute_raise__raise_number.py +0 -2
  598. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_call_via_var.py +0 -4
  599. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_direct.py +0 -3
  600. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_via_var.py +0 -4
  601. package/ref-monty/crates/monty/test_cases/ext_call__arg_side_effect_bug.py +0 -22
  602. package/ref-monty/crates/monty/test_cases/ext_call__augmented.py +0 -17
  603. package/ref-monty/crates/monty/test_cases/ext_call__augmented_refcount_bug.py +0 -7
  604. package/ref-monty/crates/monty/test_cases/ext_call__bare_raise_after_resume.py +0 -34
  605. package/ref-monty/crates/monty/test_cases/ext_call__basic.py +0 -99
  606. package/ref-monty/crates/monty/test_cases/ext_call__boolean.py +0 -37
  607. package/ref-monty/crates/monty/test_cases/ext_call__boolean_side_effect_hang.py +0 -17
  608. package/ref-monty/crates/monty/test_cases/ext_call__closure_bug.py +0 -16
  609. package/ref-monty/crates/monty/test_cases/ext_call__comparison.py +0 -26
  610. package/ref-monty/crates/monty/test_cases/ext_call__deep_call_stack.py +0 -18
  611. package/ref-monty/crates/monty/test_cases/ext_call__elif.py +0 -171
  612. package/ref-monty/crates/monty/test_cases/ext_call__exc.py +0 -4
  613. package/ref-monty/crates/monty/test_cases/ext_call__exc_deep_stack.py +0 -39
  614. package/ref-monty/crates/monty/test_cases/ext_call__exc_in_function.py +0 -17
  615. package/ref-monty/crates/monty/test_cases/ext_call__exc_nested_functions.py +0 -31
  616. package/ref-monty/crates/monty/test_cases/ext_call__ext_exc.py +0 -171
  617. package/ref-monty/crates/monty/test_cases/ext_call__for.py +0 -114
  618. package/ref-monty/crates/monty/test_cases/ext_call__fstring.py +0 -12
  619. package/ref-monty/crates/monty/test_cases/ext_call__if.py +0 -135
  620. package/ref-monty/crates/monty/test_cases/ext_call__if_condition.py +0 -37
  621. package/ref-monty/crates/monty/test_cases/ext_call__in_closure.py +0 -14
  622. package/ref-monty/crates/monty/test_cases/ext_call__in_function.py +0 -40
  623. package/ref-monty/crates/monty/test_cases/ext_call__in_function_simple.py +0 -7
  624. package/ref-monty/crates/monty/test_cases/ext_call__literals.py +0 -17
  625. package/ref-monty/crates/monty/test_cases/ext_call__multi_in_func.py +0 -32
  626. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup.py +0 -69
  627. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup_undefined.py +0 -4
  628. package/ref-monty/crates/monty/test_cases/ext_call__nested_calls.py +0 -14
  629. package/ref-monty/crates/monty/test_cases/ext_call__recursion_bug.py +0 -19
  630. package/ref-monty/crates/monty/test_cases/ext_call__return.py +0 -28
  631. package/ref-monty/crates/monty/test_cases/ext_call__side_effects.py +0 -25
  632. package/ref-monty/crates/monty/test_cases/ext_call__subscript.py +0 -7
  633. package/ref-monty/crates/monty/test_cases/ext_call__ternary.py +0 -28
  634. package/ref-monty/crates/monty/test_cases/ext_call__try.py +0 -280
  635. package/ref-monty/crates/monty/test_cases/ext_call__try_simple.py +0 -10
  636. package/ref-monty/crates/monty/test_cases/ext_call__unary.py +0 -13
  637. package/ref-monty/crates/monty/test_cases/frozenset__ops.py +0 -178
  638. package/ref-monty/crates/monty/test_cases/fstring__all.py +0 -236
  639. package/ref-monty/crates/monty/test_cases/fstring__error_eq_align_on_str.py +0 -3
  640. package/ref-monty/crates/monty/test_cases/fstring__error_float_f_on_str.py +0 -3
  641. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_float.py +0 -3
  642. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_str.py +0 -3
  643. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec.py +0 -4
  644. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_dynamic.py +0 -4
  645. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_str.py +0 -4
  646. package/ref-monty/crates/monty/test_cases/fstring__error_str_s_on_int.py +0 -3
  647. package/ref-monty/crates/monty/test_cases/function__call_duplicate_kwargs.py +0 -6
  648. package/ref-monty/crates/monty/test_cases/function__call_unpack.py +0 -42
  649. package/ref-monty/crates/monty/test_cases/function__defaults.py +0 -117
  650. package/ref-monty/crates/monty/test_cases/function__err_duplicate_arg.py +0 -7
  651. package/ref-monty/crates/monty/test_cases/function__err_duplicate_first_arg.py +0 -7
  652. package/ref-monty/crates/monty/test_cases/function__err_duplicate_kwarg_cleanup.py +0 -9
  653. package/ref-monty/crates/monty/test_cases/function__err_kwonly_as_positional.py +0 -7
  654. package/ref-monty/crates/monty/test_cases/function__err_missing_all_posonly.py +0 -7
  655. package/ref-monty/crates/monty/test_cases/function__err_missing_heap_cleanup.py +0 -9
  656. package/ref-monty/crates/monty/test_cases/function__err_missing_kwonly.py +0 -7
  657. package/ref-monty/crates/monty/test_cases/function__err_missing_posonly_with_kwarg.py +0 -7
  658. package/ref-monty/crates/monty/test_cases/function__err_missing_with_posonly.py +0 -7
  659. package/ref-monty/crates/monty/test_cases/function__err_posonly_as_kwarg.py +0 -7
  660. package/ref-monty/crates/monty/test_cases/function__err_posonly_first_as_kwarg.py +0 -7
  661. package/ref-monty/crates/monty/test_cases/function__err_too_many_posonly.py +0 -7
  662. package/ref-monty/crates/monty/test_cases/function__err_too_many_with_kwonly.py +0 -7
  663. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg.py +0 -7
  664. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_cleanup.py +0 -9
  665. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_quote.py +0 -13
  666. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_simple.py +0 -7
  667. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_arg.py +0 -6
  668. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_heap.py +0 -8
  669. package/ref-monty/crates/monty/test_cases/function__err_unpack_int.py +0 -6
  670. package/ref-monty/crates/monty/test_cases/function__err_unpack_nonstring_key.py +0 -6
  671. package/ref-monty/crates/monty/test_cases/function__err_unpack_not_mapping.py +0 -6
  672. package/ref-monty/crates/monty/test_cases/function__kwargs_unpacking.py +0 -173
  673. package/ref-monty/crates/monty/test_cases/function__ops.py +0 -294
  674. package/ref-monty/crates/monty/test_cases/function__return_none.py +0 -42
  675. package/ref-monty/crates/monty/test_cases/function__signatures.py +0 -47
  676. package/ref-monty/crates/monty/test_cases/function__too_few_args_all.py +0 -6
  677. package/ref-monty/crates/monty/test_cases/function__too_few_args_one.py +0 -6
  678. package/ref-monty/crates/monty/test_cases/function__too_few_args_two.py +0 -6
  679. package/ref-monty/crates/monty/test_cases/function__too_many_args_one.py +0 -6
  680. package/ref-monty/crates/monty/test_cases/function__too_many_args_two.py +0 -6
  681. package/ref-monty/crates/monty/test_cases/function__too_many_args_zero.py +0 -6
  682. package/ref-monty/crates/monty/test_cases/global__error_assigned_before.py +0 -7
  683. package/ref-monty/crates/monty/test_cases/global__ops.py +0 -163
  684. package/ref-monty/crates/monty/test_cases/hash__dict_unhashable.py +0 -2
  685. package/ref-monty/crates/monty/test_cases/hash__list_unhashable.py +0 -2
  686. package/ref-monty/crates/monty/test_cases/hash__ops.py +0 -153
  687. package/ref-monty/crates/monty/test_cases/id__bytes_literals_distinct.py +0 -3
  688. package/ref-monty/crates/monty/test_cases/id__int_copy_distinct.py +0 -5
  689. package/ref-monty/crates/monty/test_cases/id__is_number_is_number.py +0 -3
  690. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_distinct_types.py +0 -10
  691. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_same_types.py +0 -6
  692. package/ref-monty/crates/monty/test_cases/id__ops.py +0 -97
  693. package/ref-monty/crates/monty/test_cases/id__str_literals_same.py +0 -3
  694. package/ref-monty/crates/monty/test_cases/if__elif_else.py +0 -207
  695. package/ref-monty/crates/monty/test_cases/if__raise_elif.py +0 -11
  696. package/ref-monty/crates/monty/test_cases/if__raise_else.py +0 -13
  697. package/ref-monty/crates/monty/test_cases/if__raise_if.py +0 -9
  698. package/ref-monty/crates/monty/test_cases/if__raise_in_elif_condition.py +0 -18
  699. package/ref-monty/crates/monty/test_cases/if__raise_in_if_condition.py +0 -16
  700. package/ref-monty/crates/monty/test_cases/if_else_expr__all.py +0 -55
  701. package/ref-monty/crates/monty/test_cases/import__error_cannot_import.py +0 -9
  702. package/ref-monty/crates/monty/test_cases/import__error_module_not_found.py +0 -9
  703. package/ref-monty/crates/monty/test_cases/import__local_scope.py +0 -68
  704. package/ref-monty/crates/monty/test_cases/import__os.py +0 -25
  705. package/ref-monty/crates/monty/test_cases/import__relative_error.py +0 -9
  706. package/ref-monty/crates/monty/test_cases/import__relative_no_module_error.py +0 -9
  707. package/ref-monty/crates/monty/test_cases/import__runtime_error_when_executed.py +0 -14
  708. package/ref-monty/crates/monty/test_cases/import__star_error.py +0 -11
  709. package/ref-monty/crates/monty/test_cases/import__sys.py +0 -47
  710. package/ref-monty/crates/monty/test_cases/import__sys_monty.py +0 -28
  711. package/ref-monty/crates/monty/test_cases/import__type_checking_guard.py +0 -37
  712. package/ref-monty/crates/monty/test_cases/import__typing.py +0 -25
  713. package/ref-monty/crates/monty/test_cases/import__typing_type_ignore.py +0 -4
  714. package/ref-monty/crates/monty/test_cases/int__bigint.py +0 -467
  715. package/ref-monty/crates/monty/test_cases/int__bigint_errors.py +0 -260
  716. package/ref-monty/crates/monty/test_cases/int__ops.py +0 -219
  717. package/ref-monty/crates/monty/test_cases/int__overflow_division.py +0 -84
  718. package/ref-monty/crates/monty/test_cases/is_variant__all.py +0 -36
  719. package/ref-monty/crates/monty/test_cases/isinstance__arg2_list_error.py +0 -2
  720. package/ref-monty/crates/monty/test_cases/isinstance__arg2_type_error.py +0 -2
  721. package/ref-monty/crates/monty/test_cases/iter__dict_mutation.py +0 -4
  722. package/ref-monty/crates/monty/test_cases/iter__for.py +0 -243
  723. package/ref-monty/crates/monty/test_cases/iter__for_loop_unpacking.py +0 -66
  724. package/ref-monty/crates/monty/test_cases/iter__generator_expr.py +0 -20
  725. package/ref-monty/crates/monty/test_cases/iter__generator_expr_type.py +0 -7
  726. package/ref-monty/crates/monty/test_cases/iter__not_iterable.py +0 -3
  727. package/ref-monty/crates/monty/test_cases/lambda__all.py +0 -145
  728. package/ref-monty/crates/monty/test_cases/list__extend_not_iterable.py +0 -7
  729. package/ref-monty/crates/monty/test_cases/list__getitem_out_of_bounds.py +0 -3
  730. package/ref-monty/crates/monty/test_cases/list__index_not_found.py +0 -9
  731. package/ref-monty/crates/monty/test_cases/list__index_start_gt_end.py +0 -10
  732. package/ref-monty/crates/monty/test_cases/list__ops.py +0 -473
  733. package/ref-monty/crates/monty/test_cases/list__pop_empty.py +0 -9
  734. package/ref-monty/crates/monty/test_cases/list__pop_out_of_range.py +0 -9
  735. package/ref-monty/crates/monty/test_cases/list__pop_type_error.py +0 -9
  736. package/ref-monty/crates/monty/test_cases/list__remove_not_found.py +0 -9
  737. package/ref-monty/crates/monty/test_cases/list__setitem_dict_index.py +0 -13
  738. package/ref-monty/crates/monty/test_cases/list__setitem_huge_int_index.py +0 -13
  739. package/ref-monty/crates/monty/test_cases/list__setitem_index_error.py +0 -10
  740. package/ref-monty/crates/monty/test_cases/list__setitem_type_error.py +0 -10
  741. package/ref-monty/crates/monty/test_cases/list__unpack_type_error.py +0 -2
  742. package/ref-monty/crates/monty/test_cases/longint__index_error.py +0 -3
  743. package/ref-monty/crates/monty/test_cases/longint__repeat_error.py +0 -3
  744. package/ref-monty/crates/monty/test_cases/loop__break_continue.py +0 -113
  745. package/ref-monty/crates/monty/test_cases/loop__break_finally.py +0 -69
  746. package/ref-monty/crates/monty/test_cases/loop__break_in_function_error.py +0 -13
  747. package/ref-monty/crates/monty/test_cases/loop__break_in_if_error.py +0 -11
  748. package/ref-monty/crates/monty/test_cases/loop__break_nested_except_clears.py +0 -55
  749. package/ref-monty/crates/monty/test_cases/loop__break_outside_error.py +0 -9
  750. package/ref-monty/crates/monty/test_cases/loop__continue_finally.py +0 -81
  751. package/ref-monty/crates/monty/test_cases/loop__continue_in_function_error.py +0 -13
  752. package/ref-monty/crates/monty/test_cases/loop__continue_in_if_error.py +0 -11
  753. package/ref-monty/crates/monty/test_cases/loop__continue_nested_except_clears.py +0 -60
  754. package/ref-monty/crates/monty/test_cases/loop__continue_outside_error.py +0 -9
  755. package/ref-monty/crates/monty/test_cases/math__acos_domain_error.py +0 -11
  756. package/ref-monty/crates/monty/test_cases/math__acosh_domain_error.py +0 -11
  757. package/ref-monty/crates/monty/test_cases/math__asin_domain_error.py +0 -11
  758. package/ref-monty/crates/monty/test_cases/math__atanh_domain_error.py +0 -11
  759. package/ref-monty/crates/monty/test_cases/math__cos_inf_error.py +0 -11
  760. package/ref-monty/crates/monty/test_cases/math__cosh_overflow_error.py +0 -11
  761. package/ref-monty/crates/monty/test_cases/math__exp_overflow_error.py +0 -11
  762. package/ref-monty/crates/monty/test_cases/math__factorial_float_error.py +0 -11
  763. package/ref-monty/crates/monty/test_cases/math__factorial_negative_error.py +0 -11
  764. package/ref-monty/crates/monty/test_cases/math__floor_inf_error.py +0 -11
  765. package/ref-monty/crates/monty/test_cases/math__floor_nan_error.py +0 -11
  766. package/ref-monty/crates/monty/test_cases/math__floor_str_error.py +0 -11
  767. package/ref-monty/crates/monty/test_cases/math__fmod_inf_error.py +0 -11
  768. package/ref-monty/crates/monty/test_cases/math__gamma_neg_int_error.py +0 -11
  769. package/ref-monty/crates/monty/test_cases/math__gcd_float_error.py +0 -11
  770. package/ref-monty/crates/monty/test_cases/math__isqrt_negative_error.py +0 -11
  771. package/ref-monty/crates/monty/test_cases/math__ldexp_overflow_error.py +0 -11
  772. package/ref-monty/crates/monty/test_cases/math__log1p_domain_error.py +0 -11
  773. package/ref-monty/crates/monty/test_cases/math__log_base1_error.py +0 -11
  774. package/ref-monty/crates/monty/test_cases/math__log_zero_error.py +0 -11
  775. package/ref-monty/crates/monty/test_cases/math__module.py +0 -1432
  776. package/ref-monty/crates/monty/test_cases/math__pow_domain_error.py +0 -11
  777. package/ref-monty/crates/monty/test_cases/math__sin_inf_error.py +0 -11
  778. package/ref-monty/crates/monty/test_cases/math__sqrt_negative_error.py +0 -11
  779. package/ref-monty/crates/monty/test_cases/math__tan_inf_error.py +0 -11
  780. package/ref-monty/crates/monty/test_cases/math__trunc_str_error.py +0 -11
  781. package/ref-monty/crates/monty/test_cases/method__args_kwargs_unpacking.py +0 -259
  782. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_func.py +0 -19
  783. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_module.py +0 -12
  784. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_chained.py +0 -9
  785. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_expr.py +0 -9
  786. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_function.py +0 -16
  787. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_with_args.py +0 -9
  788. package/ref-monty/crates/monty/test_cases/name_error__undefined_global.py +0 -10
  789. package/ref-monty/crates/monty/test_cases/namedtuple__missing_attr.py +0 -11
  790. package/ref-monty/crates/monty/test_cases/namedtuple__ops.py +0 -34
  791. package/ref-monty/crates/monty/test_cases/nonlocal__error_module_level.py +0 -3
  792. package/ref-monty/crates/monty/test_cases/nonlocal__ops.py +0 -353
  793. package/ref-monty/crates/monty/test_cases/os__environ.py +0 -40
  794. package/ref-monty/crates/monty/test_cases/os__getenv_key_list_error.py +0 -5
  795. package/ref-monty/crates/monty/test_cases/os__getenv_key_type_error.py +0 -5
  796. package/ref-monty/crates/monty/test_cases/parse_error__complex.py +0 -3
  797. package/ref-monty/crates/monty/test_cases/pathlib__import.py +0 -11
  798. package/ref-monty/crates/monty/test_cases/pathlib__os.py +0 -136
  799. package/ref-monty/crates/monty/test_cases/pathlib__os_read_error.py +0 -12
  800. package/ref-monty/crates/monty/test_cases/pathlib__pure.py +0 -81
  801. package/ref-monty/crates/monty/test_cases/pyobject__cycle_dict_self.py +0 -5
  802. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_dict.py +0 -6
  803. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_self.py +0 -5
  804. package/ref-monty/crates/monty/test_cases/pyobject__cycle_multiple_refs.py +0 -6
  805. package/ref-monty/crates/monty/test_cases/range__error_no_args.py +0 -2
  806. package/ref-monty/crates/monty/test_cases/range__error_step_zero.py +0 -2
  807. package/ref-monty/crates/monty/test_cases/range__error_too_many_args.py +0 -2
  808. package/ref-monty/crates/monty/test_cases/range__getitem_index_error.py +0 -10
  809. package/ref-monty/crates/monty/test_cases/range__ops.py +0 -236
  810. package/ref-monty/crates/monty/test_cases/re__basic.py +0 -756
  811. package/ref-monty/crates/monty/test_cases/re__grouping.py +0 -241
  812. package/ref-monty/crates/monty/test_cases/re__match.py +0 -148
  813. package/ref-monty/crates/monty/test_cases/recursion__deep_drop.py +0 -26
  814. package/ref-monty/crates/monty/test_cases/recursion__deep_eq.py +0 -23
  815. package/ref-monty/crates/monty/test_cases/recursion__deep_hash.py +0 -46
  816. package/ref-monty/crates/monty/test_cases/recursion__deep_repr.py +0 -12
  817. package/ref-monty/crates/monty/test_cases/recursion__function_depth.py +0 -13
  818. package/ref-monty/crates/monty/test_cases/refcount__cycle_mutual_reference.py +0 -18
  819. package/ref-monty/crates/monty/test_cases/refcount__cycle_self_reference.py +0 -12
  820. package/ref-monty/crates/monty/test_cases/refcount__dict_basic.py +0 -5
  821. package/ref-monty/crates/monty/test_cases/refcount__dict_get.py +0 -5
  822. package/ref-monty/crates/monty/test_cases/refcount__dict_keys_and.py +0 -14
  823. package/ref-monty/crates/monty/test_cases/refcount__dict_overwrite.py +0 -6
  824. package/ref-monty/crates/monty/test_cases/refcount__gather_cleanup.py +0 -16
  825. package/ref-monty/crates/monty/test_cases/refcount__gather_exception.py +0 -18
  826. package/ref-monty/crates/monty/test_cases/refcount__gather_nested_cancel.py +0 -25
  827. package/ref-monty/crates/monty/test_cases/refcount__immediate_skipped.py +0 -4
  828. package/ref-monty/crates/monty/test_cases/refcount__kwargs_unpacking.py +0 -27
  829. package/ref-monty/crates/monty/test_cases/refcount__list_append_multiple.py +0 -6
  830. package/ref-monty/crates/monty/test_cases/refcount__list_append_ref.py +0 -5
  831. package/ref-monty/crates/monty/test_cases/refcount__list_concat.py +0 -5
  832. package/ref-monty/crates/monty/test_cases/refcount__list_getitem.py +0 -5
  833. package/ref-monty/crates/monty/test_cases/refcount__list_iadd.py +0 -5
  834. package/ref-monty/crates/monty/test_cases/refcount__nested_list.py +0 -4
  835. package/ref-monty/crates/monty/test_cases/refcount__re_pattern_sub_error_paths.py +0 -37
  836. package/ref-monty/crates/monty/test_cases/refcount__re_search_match.py +0 -34
  837. package/ref-monty/crates/monty/test_cases/refcount__re_sub_error_paths.py +0 -31
  838. package/ref-monty/crates/monty/test_cases/refcount__shared_reference.py +0 -4
  839. package/ref-monty/crates/monty/test_cases/refcount__single_list.py +0 -3
  840. package/ref-monty/crates/monty/test_cases/repr__cycle_detection.py +0 -24
  841. package/ref-monty/crates/monty/test_cases/set__ops.py +0 -191
  842. package/ref-monty/crates/monty/test_cases/set__review_bugs.py +0 -35
  843. package/ref-monty/crates/monty/test_cases/set__unpack_type_error.py +0 -2
  844. package/ref-monty/crates/monty/test_cases/slice__invalid_indices.py +0 -2
  845. package/ref-monty/crates/monty/test_cases/slice__kwargs.py +0 -9
  846. package/ref-monty/crates/monty/test_cases/slice__no_args.py +0 -9
  847. package/ref-monty/crates/monty/test_cases/slice__ops.py +0 -149
  848. package/ref-monty/crates/monty/test_cases/slice__step_zero.py +0 -9
  849. package/ref-monty/crates/monty/test_cases/slice__step_zero_bytes.py +0 -9
  850. package/ref-monty/crates/monty/test_cases/slice__step_zero_range.py +0 -9
  851. package/ref-monty/crates/monty/test_cases/slice__step_zero_str.py +0 -9
  852. package/ref-monty/crates/monty/test_cases/slice__step_zero_tuple.py +0 -9
  853. package/ref-monty/crates/monty/test_cases/slice__too_many_args.py +0 -9
  854. package/ref-monty/crates/monty/test_cases/str__getitem_index_error.py +0 -10
  855. package/ref-monty/crates/monty/test_cases/str__index_not_found.py +0 -9
  856. package/ref-monty/crates/monty/test_cases/str__join_no_args.py +0 -9
  857. package/ref-monty/crates/monty/test_cases/str__join_non_string.py +0 -9
  858. package/ref-monty/crates/monty/test_cases/str__join_not_iterable.py +0 -9
  859. package/ref-monty/crates/monty/test_cases/str__join_too_many_args.py +0 -9
  860. package/ref-monty/crates/monty/test_cases/str__methods.py +0 -327
  861. package/ref-monty/crates/monty/test_cases/str__ops.py +0 -162
  862. package/ref-monty/crates/monty/test_cases/str__partition_empty.py +0 -9
  863. package/ref-monty/crates/monty/test_cases/str__rsplit_empty_sep.py +0 -9
  864. package/ref-monty/crates/monty/test_cases/str__split_empty_sep.py +0 -9
  865. package/ref-monty/crates/monty/test_cases/sys__types.py +0 -7
  866. package/ref-monty/crates/monty/test_cases/traceback__division_error.py +0 -30
  867. package/ref-monty/crates/monty/test_cases/traceback__index_error.py +0 -17
  868. package/ref-monty/crates/monty/test_cases/traceback__insert_as_int.py +0 -10
  869. package/ref-monty/crates/monty/test_cases/traceback__nested_call.py +0 -29
  870. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_module_scope.py +0 -10
  871. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_unbound.py +0 -24
  872. package/ref-monty/crates/monty/test_cases/traceback__range_as_int.py +0 -9
  873. package/ref-monty/crates/monty/test_cases/traceback__recursion_error.py +0 -23
  874. package/ref-monty/crates/monty/test_cases/traceback__set_mutation.py +0 -11
  875. package/ref-monty/crates/monty/test_cases/traceback__undefined_attr_call.py +0 -16
  876. package/ref-monty/crates/monty/test_cases/traceback__undefined_call.py +0 -16
  877. package/ref-monty/crates/monty/test_cases/traceback__undefined_raise.py +0 -16
  878. package/ref-monty/crates/monty/test_cases/try_except__all.py +0 -472
  879. package/ref-monty/crates/monty/test_cases/try_except__bare_raise_no_context.py +0 -2
  880. package/ref-monty/crates/monty/test_cases/try_except__invalid_type.py +0 -5
  881. package/ref-monty/crates/monty/test_cases/tuple__getitem_out_of_bounds.py +0 -3
  882. package/ref-monty/crates/monty/test_cases/tuple__index_not_found.py +0 -9
  883. package/ref-monty/crates/monty/test_cases/tuple__index_start_gt_end.py +0 -10
  884. package/ref-monty/crates/monty/test_cases/tuple__methods.py +0 -19
  885. package/ref-monty/crates/monty/test_cases/tuple__ops.py +0 -133
  886. package/ref-monty/crates/monty/test_cases/tuple__unpack_type_error.py +0 -2
  887. package/ref-monty/crates/monty/test_cases/type__builtin_attr_error.py +0 -9
  888. package/ref-monty/crates/monty/test_cases/type__bytes_negative.py +0 -2
  889. package/ref-monty/crates/monty/test_cases/type__cell_not_builtin.py +0 -9
  890. package/ref-monty/crates/monty/test_cases/type__exception_attr_error.py +0 -11
  891. package/ref-monty/crates/monty/test_cases/type__float_conversion_error.py +0 -2
  892. package/ref-monty/crates/monty/test_cases/type__float_repr_both_quotes.py +0 -9
  893. package/ref-monty/crates/monty/test_cases/type__float_repr_newline.py +0 -9
  894. package/ref-monty/crates/monty/test_cases/type__float_repr_single_quote.py +0 -9
  895. package/ref-monty/crates/monty/test_cases/type__int_conversion_error.py +0 -2
  896. package/ref-monty/crates/monty/test_cases/type__list_not_iterable.py +0 -2
  897. package/ref-monty/crates/monty/test_cases/type__non_builtin_name_error.py +0 -9
  898. package/ref-monty/crates/monty/test_cases/type__ops.py +0 -200
  899. package/ref-monty/crates/monty/test_cases/type__shadow_exc.py +0 -3
  900. package/ref-monty/crates/monty/test_cases/type__shadow_int.py +0 -9
  901. package/ref-monty/crates/monty/test_cases/type__shadow_len.py +0 -3
  902. package/ref-monty/crates/monty/test_cases/type__tuple_not_iterable.py +0 -2
  903. package/ref-monty/crates/monty/test_cases/type_error__int_add_list.py +0 -2
  904. package/ref-monty/crates/monty/test_cases/type_error__int_div_str.py +0 -2
  905. package/ref-monty/crates/monty/test_cases/type_error__int_floordiv_str.py +0 -2
  906. package/ref-monty/crates/monty/test_cases/type_error__int_iadd_str.py +0 -3
  907. package/ref-monty/crates/monty/test_cases/type_error__int_mod_str.py +0 -2
  908. package/ref-monty/crates/monty/test_cases/type_error__int_pow_str.py +0 -2
  909. package/ref-monty/crates/monty/test_cases/type_error__int_sub_str.py +0 -2
  910. package/ref-monty/crates/monty/test_cases/type_error__list_add_int.py +0 -2
  911. package/ref-monty/crates/monty/test_cases/type_error__list_add_str.py +0 -2
  912. package/ref-monty/crates/monty/test_cases/type_error__list_iadd_int.py +0 -6
  913. package/ref-monty/crates/monty/test_cases/type_error__str_add_int.py +0 -2
  914. package/ref-monty/crates/monty/test_cases/type_error__str_iadd_int.py +0 -3
  915. package/ref-monty/crates/monty/test_cases/type_error__unary_invert_str.py +0 -3
  916. package/ref-monty/crates/monty/test_cases/type_error__unary_minus_str.py +0 -4
  917. package/ref-monty/crates/monty/test_cases/type_error__unary_neg_str.py +0 -3
  918. package/ref-monty/crates/monty/test_cases/type_error__unary_plus_str.py +0 -4
  919. package/ref-monty/crates/monty/test_cases/typing__types.py +0 -24
  920. package/ref-monty/crates/monty/test_cases/unpack__nested.py +0 -48
  921. package/ref-monty/crates/monty/test_cases/unpack__non_sequence.py +0 -9
  922. package/ref-monty/crates/monty/test_cases/unpack__not_enough.py +0 -9
  923. package/ref-monty/crates/monty/test_cases/unpack__ops.py +0 -153
  924. package/ref-monty/crates/monty/test_cases/unpack__star_not_enough.py +0 -9
  925. package/ref-monty/crates/monty/test_cases/unpack__too_many.py +0 -9
  926. package/ref-monty/crates/monty/test_cases/version__cpython.py +0 -4
  927. package/ref-monty/crates/monty/test_cases/walrus__all.py +0 -178
  928. package/ref-monty/crates/monty/test_cases/while__all.py +0 -206
  929. package/ref-monty/crates/monty/tests/asyncio.rs +0 -764
  930. package/ref-monty/crates/monty/tests/binary_serde.rs +0 -185
  931. package/ref-monty/crates/monty/tests/bytecode_limits.rs +0 -248
  932. package/ref-monty/crates/monty/tests/datatest_runner.rs +0 -2029
  933. package/ref-monty/crates/monty/tests/inputs.rs +0 -420
  934. package/ref-monty/crates/monty/tests/json_serde.rs +0 -250
  935. package/ref-monty/crates/monty/tests/main.rs +0 -71
  936. package/ref-monty/crates/monty/tests/math_module.rs +0 -114
  937. package/ref-monty/crates/monty/tests/name_lookup.rs +0 -482
  938. package/ref-monty/crates/monty/tests/os_tests.rs +0 -459
  939. package/ref-monty/crates/monty/tests/parse_errors.rs +0 -441
  940. package/ref-monty/crates/monty/tests/print_writer.rs +0 -238
  941. package/ref-monty/crates/monty/tests/py_object.rs +0 -121
  942. package/ref-monty/crates/monty/tests/regex.rs +0 -90
  943. package/ref-monty/crates/monty/tests/repl.rs +0 -344
  944. package/ref-monty/crates/monty/tests/resource_limits.rs +0 -1826
  945. package/ref-monty/crates/monty/tests/try_from.rs +0 -167
  946. package/ref-monty/crates/monty-cli/Cargo.toml +0 -25
  947. package/ref-monty/crates/monty-cli/src/main.rs +0 -541
  948. package/ref-monty/crates/monty-js/.cargo/config.toml +0 -2
  949. package/ref-monty/crates/monty-js/.prettierignore +0 -8
  950. package/ref-monty/crates/monty-js/Cargo.toml +0 -32
  951. package/ref-monty/crates/monty-js/README.md +0 -207
  952. package/ref-monty/crates/monty-js/__test__/async.spec.ts +0 -350
  953. package/ref-monty/crates/monty-js/__test__/basic.spec.ts +0 -114
  954. package/ref-monty/crates/monty-js/__test__/exceptions.spec.ts +0 -427
  955. package/ref-monty/crates/monty-js/__test__/external.spec.ts +0 -354
  956. package/ref-monty/crates/monty-js/__test__/inputs.spec.ts +0 -143
  957. package/ref-monty/crates/monty-js/__test__/limits.spec.ts +0 -162
  958. package/ref-monty/crates/monty-js/__test__/package.json +0 -3
  959. package/ref-monty/crates/monty-js/__test__/print.spec.ts +0 -229
  960. package/ref-monty/crates/monty-js/__test__/repl.spec.ts +0 -34
  961. package/ref-monty/crates/monty-js/__test__/serialize.spec.ts +0 -205
  962. package/ref-monty/crates/monty-js/__test__/start.spec.ts +0 -443
  963. package/ref-monty/crates/monty-js/__test__/type_check.spec.ts +0 -147
  964. package/ref-monty/crates/monty-js/__test__/types.spec.ts +0 -319
  965. package/ref-monty/crates/monty-js/build.rs +0 -61
  966. package/ref-monty/crates/monty-js/index-header.d.ts +0 -3
  967. package/ref-monty/crates/monty-js/package-lock.json +0 -4694
  968. package/ref-monty/crates/monty-js/package.json +0 -100
  969. package/ref-monty/crates/monty-js/scripts/smoke-test.sh +0 -69
  970. package/ref-monty/crates/monty-js/smoke-test/package.json +0 -17
  971. package/ref-monty/crates/monty-js/smoke-test/test.ts +0 -171
  972. package/ref-monty/crates/monty-js/smoke-test/tsconfig.json +0 -11
  973. package/ref-monty/crates/monty-js/src/convert.rs +0 -648
  974. package/ref-monty/crates/monty-js/src/exceptions.rs +0 -293
  975. package/ref-monty/crates/monty-js/src/lib.rs +0 -41
  976. package/ref-monty/crates/monty-js/src/limits.rs +0 -53
  977. package/ref-monty/crates/monty-js/src/monty_cls.rs +0 -1407
  978. package/ref-monty/crates/monty-js/tsconfig.json +0 -17
  979. package/ref-monty/crates/monty-js/wrapper.ts +0 -701
  980. package/ref-monty/crates/monty-python/Cargo.toml +0 -38
  981. package/ref-monty/crates/monty-python/README.md +0 -134
  982. package/ref-monty/crates/monty-python/build.rs +0 -4
  983. package/ref-monty/crates/monty-python/example.py +0 -40
  984. package/ref-monty/crates/monty-python/exercise.py +0 -46
  985. package/ref-monty/crates/monty-python/pyproject.toml +0 -57
  986. package/ref-monty/crates/monty-python/python/pydantic_monty/__init__.py +0 -281
  987. package/ref-monty/crates/monty-python/python/pydantic_monty/_monty.pyi +0 -677
  988. package/ref-monty/crates/monty-python/python/pydantic_monty/os_access.py +0 -933
  989. package/ref-monty/crates/monty-python/python/pydantic_monty/py.typed +0 -0
  990. package/ref-monty/crates/monty-python/src/convert.rs +0 -273
  991. package/ref-monty/crates/monty-python/src/dataclass.rs +0 -461
  992. package/ref-monty/crates/monty-python/src/exceptions.rs +0 -557
  993. package/ref-monty/crates/monty-python/src/external.rs +0 -165
  994. package/ref-monty/crates/monty-python/src/lib.rs +0 -77
  995. package/ref-monty/crates/monty-python/src/limits.rs +0 -142
  996. package/ref-monty/crates/monty-python/src/monty_cls.rs +0 -1650
  997. package/ref-monty/crates/monty-python/src/repl.rs +0 -470
  998. package/ref-monty/crates/monty-python/src/serialization.rs +0 -761
  999. package/ref-monty/crates/monty-python/tests/test_async.py +0 -1201
  1000. package/ref-monty/crates/monty-python/tests/test_basic.py +0 -66
  1001. package/ref-monty/crates/monty-python/tests/test_dataclasses.py +0 -971
  1002. package/ref-monty/crates/monty-python/tests/test_exceptions.py +0 -361
  1003. package/ref-monty/crates/monty-python/tests/test_external.py +0 -367
  1004. package/ref-monty/crates/monty-python/tests/test_inputs.py +0 -126
  1005. package/ref-monty/crates/monty-python/tests/test_limits.py +0 -257
  1006. package/ref-monty/crates/monty-python/tests/test_os_access.py +0 -1286
  1007. package/ref-monty/crates/monty-python/tests/test_os_access_compat.py +0 -731
  1008. package/ref-monty/crates/monty-python/tests/test_os_access_raw.py +0 -483
  1009. package/ref-monty/crates/monty-python/tests/test_os_calls.py +0 -819
  1010. package/ref-monty/crates/monty-python/tests/test_print.py +0 -208
  1011. package/ref-monty/crates/monty-python/tests/test_re.py +0 -170
  1012. package/ref-monty/crates/monty-python/tests/test_readme_examples.py +0 -20
  1013. package/ref-monty/crates/monty-python/tests/test_repl.py +0 -749
  1014. package/ref-monty/crates/monty-python/tests/test_serialize.py +0 -284
  1015. package/ref-monty/crates/monty-python/tests/test_start.py +0 -346
  1016. package/ref-monty/crates/monty-python/tests/test_threading.py +0 -163
  1017. package/ref-monty/crates/monty-python/tests/test_type_check.py +0 -344
  1018. package/ref-monty/crates/monty-python/tests/test_types.py +0 -553
  1019. package/ref-monty/crates/monty-type-checking/Cargo.toml +0 -32
  1020. package/ref-monty/crates/monty-type-checking/src/db.rs +0 -116
  1021. package/ref-monty/crates/monty-type-checking/src/lib.rs +0 -4
  1022. package/ref-monty/crates/monty-type-checking/src/type_check.rs +0 -280
  1023. package/ref-monty/crates/monty-type-checking/tests/bad_types.py +0 -109
  1024. package/ref-monty/crates/monty-type-checking/tests/bad_types_output.txt +0 -21
  1025. package/ref-monty/crates/monty-type-checking/tests/good_types.py +0 -475
  1026. package/ref-monty/crates/monty-type-checking/tests/main.rs +0 -205
  1027. package/ref-monty/crates/monty-type-checking/tests/reveal_types.py +0 -56
  1028. package/ref-monty/crates/monty-type-checking/tests/reveal_types_output.txt +0 -41
  1029. package/ref-monty/crates/monty-typeshed/Cargo.toml +0 -29
  1030. package/ref-monty/crates/monty-typeshed/README.md +0 -11
  1031. package/ref-monty/crates/monty-typeshed/build.rs +0 -101
  1032. package/ref-monty/crates/monty-typeshed/custom/README.md +0 -1
  1033. package/ref-monty/crates/monty-typeshed/custom/asyncio.pyi +0 -138
  1034. package/ref-monty/crates/monty-typeshed/custom/os.pyi +0 -87
  1035. package/ref-monty/crates/monty-typeshed/custom/sys.pyi +0 -33
  1036. package/ref-monty/crates/monty-typeshed/src/lib.rs +0 -56
  1037. package/ref-monty/crates/monty-typeshed/update.py +0 -321
  1038. package/ref-monty/crates/monty-typeshed/vendor/typeshed/source_commit.txt +0 -1
  1039. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/VERSIONS +0 -20
  1040. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi +0 -105
  1041. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi +0 -394
  1042. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi +0 -138
  1043. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi +0 -1434
  1044. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi +0 -527
  1045. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/abc.pyi +0 -2
  1046. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/dataclasses.pyi +0 -502
  1047. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/enum.pyi +0 -376
  1048. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/math.pyi +0 -149
  1049. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/os.pyi +0 -87
  1050. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/__init__.pyi +0 -395
  1051. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/types.pyi +0 -8
  1052. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/re.pyi +0 -337
  1053. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/sys.pyi +0 -33
  1054. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/types.pyi +0 -741
  1055. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing.pyi +0 -1217
  1056. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing_extensions.pyi +0 -716
  1057. package/ref-monty/docs/usage-guide.md +0 -117
  1058. package/ref-monty/examples/README.md +0 -3
  1059. package/ref-monty/examples/expense_analysis/README.md +0 -3
  1060. package/ref-monty/examples/expense_analysis/data.py +0 -124
  1061. package/ref-monty/examples/expense_analysis/main.py +0 -115
  1062. package/ref-monty/examples/sql_playground/README.md +0 -20
  1063. package/ref-monty/examples/sql_playground/external_functions.py +0 -129
  1064. package/ref-monty/examples/sql_playground/main.py +0 -81
  1065. package/ref-monty/examples/sql_playground/sandbox_code.py +0 -82
  1066. package/ref-monty/examples/sql_playground/type_stubs.pyi +0 -14
  1067. package/ref-monty/examples/web_scraper/README.md +0 -15
  1068. package/ref-monty/examples/web_scraper/browser.py +0 -56
  1069. package/ref-monty/examples/web_scraper/example_code.py +0 -59
  1070. package/ref-monty/examples/web_scraper/external_functions.py +0 -324
  1071. package/ref-monty/examples/web_scraper/main.py +0 -193
  1072. package/ref-monty/examples/web_scraper/sub_agent.py +0 -79
  1073. package/ref-monty/monty-npm.md +0 -235
  1074. package/ref-monty/pyproject.toml +0 -162
  1075. package/ref-monty/scripts/check_imports.py +0 -91
  1076. package/ref-monty/scripts/codecov_diff.py +0 -412
  1077. package/ref-monty/scripts/complete_tests.py +0 -146
  1078. package/ref-monty/scripts/flamegraph_to_text.py +0 -208
  1079. package/ref-monty/scripts/iter_test_methods.py +0 -540
  1080. package/ref-monty/scripts/run_traceback.py +0 -180
  1081. package/ref-monty/scripts/startup_performance.py +0 -130
  1082. package/ref-monty/uv.lock +0 -1779
  1083. package/temp_resend_cli/repo/.github/scripts/pr-title-check.js +0 -34
  1084. package/temp_resend_cli/repo/.github/workflows/ci.yml +0 -67
  1085. package/temp_resend_cli/repo/.github/workflows/post-release.yml +0 -51
  1086. package/temp_resend_cli/repo/.github/workflows/pr-title-check.yml +0 -13
  1087. package/temp_resend_cli/repo/.github/workflows/release.yml +0 -175
  1088. package/temp_resend_cli/repo/.github/workflows/test-install-unix.yml +0 -34
  1089. package/temp_resend_cli/repo/.github/workflows/test-install-windows.yml +0 -48
  1090. package/temp_resend_cli/repo/CHANGELOG.md +0 -31
  1091. package/temp_resend_cli/repo/LICENSE +0 -21
  1092. package/temp_resend_cli/repo/README.md +0 -450
  1093. package/temp_resend_cli/repo/biome.json +0 -36
  1094. package/temp_resend_cli/repo/install.ps1 +0 -141
  1095. package/temp_resend_cli/repo/install.sh +0 -301
  1096. package/temp_resend_cli/repo/package.json +0 -61
  1097. package/temp_resend_cli/repo/pnpm-lock.yaml +0 -2439
  1098. package/temp_resend_cli/repo/renovate.json +0 -4
  1099. package/temp_resend_cli/repo/src/cli.ts +0 -98
  1100. package/temp_resend_cli/repo/src/commands/api-keys/create.ts +0 -114
  1101. package/temp_resend_cli/repo/src/commands/api-keys/delete.ts +0 -47
  1102. package/temp_resend_cli/repo/src/commands/api-keys/index.ts +0 -26
  1103. package/temp_resend_cli/repo/src/commands/api-keys/list.ts +0 -35
  1104. package/temp_resend_cli/repo/src/commands/api-keys/utils.ts +0 -8
  1105. package/temp_resend_cli/repo/src/commands/auth/index.ts +0 -20
  1106. package/temp_resend_cli/repo/src/commands/auth/login.ts +0 -234
  1107. package/temp_resend_cli/repo/src/commands/auth/logout.ts +0 -105
  1108. package/temp_resend_cli/repo/src/commands/broadcasts/create.ts +0 -196
  1109. package/temp_resend_cli/repo/src/commands/broadcasts/delete.ts +0 -46
  1110. package/temp_resend_cli/repo/src/commands/broadcasts/get.ts +0 -59
  1111. package/temp_resend_cli/repo/src/commands/broadcasts/index.ts +0 -43
  1112. package/temp_resend_cli/repo/src/commands/broadcasts/list.ts +0 -60
  1113. package/temp_resend_cli/repo/src/commands/broadcasts/send.ts +0 -56
  1114. package/temp_resend_cli/repo/src/commands/broadcasts/update.ts +0 -95
  1115. package/temp_resend_cli/repo/src/commands/broadcasts/utils.ts +0 -35
  1116. package/temp_resend_cli/repo/src/commands/contact-properties/create.ts +0 -118
  1117. package/temp_resend_cli/repo/src/commands/contact-properties/delete.ts +0 -48
  1118. package/temp_resend_cli/repo/src/commands/contact-properties/get.ts +0 -46
  1119. package/temp_resend_cli/repo/src/commands/contact-properties/index.ts +0 -48
  1120. package/temp_resend_cli/repo/src/commands/contact-properties/list.ts +0 -68
  1121. package/temp_resend_cli/repo/src/commands/contact-properties/update.ts +0 -88
  1122. package/temp_resend_cli/repo/src/commands/contact-properties/utils.ts +0 -17
  1123. package/temp_resend_cli/repo/src/commands/contacts/add-segment.ts +0 -78
  1124. package/temp_resend_cli/repo/src/commands/contacts/create.ts +0 -122
  1125. package/temp_resend_cli/repo/src/commands/contacts/delete.ts +0 -49
  1126. package/temp_resend_cli/repo/src/commands/contacts/get.ts +0 -53
  1127. package/temp_resend_cli/repo/src/commands/contacts/index.ts +0 -58
  1128. package/temp_resend_cli/repo/src/commands/contacts/list.ts +0 -57
  1129. package/temp_resend_cli/repo/src/commands/contacts/remove-segment.ts +0 -48
  1130. package/temp_resend_cli/repo/src/commands/contacts/segments.ts +0 -39
  1131. package/temp_resend_cli/repo/src/commands/contacts/topics.ts +0 -45
  1132. package/temp_resend_cli/repo/src/commands/contacts/update-topics.ts +0 -90
  1133. package/temp_resend_cli/repo/src/commands/contacts/update.ts +0 -77
  1134. package/temp_resend_cli/repo/src/commands/contacts/utils.ts +0 -119
  1135. package/temp_resend_cli/repo/src/commands/doctor.ts +0 -216
  1136. package/temp_resend_cli/repo/src/commands/domains/create.ts +0 -83
  1137. package/temp_resend_cli/repo/src/commands/domains/delete.ts +0 -42
  1138. package/temp_resend_cli/repo/src/commands/domains/get.ts +0 -47
  1139. package/temp_resend_cli/repo/src/commands/domains/index.ts +0 -35
  1140. package/temp_resend_cli/repo/src/commands/domains/list.ts +0 -53
  1141. package/temp_resend_cli/repo/src/commands/domains/update.ts +0 -75
  1142. package/temp_resend_cli/repo/src/commands/domains/utils.ts +0 -44
  1143. package/temp_resend_cli/repo/src/commands/domains/verify.ts +0 -38
  1144. package/temp_resend_cli/repo/src/commands/emails/batch.ts +0 -140
  1145. package/temp_resend_cli/repo/src/commands/emails/get.ts +0 -44
  1146. package/temp_resend_cli/repo/src/commands/emails/index.ts +0 -30
  1147. package/temp_resend_cli/repo/src/commands/emails/list.ts +0 -84
  1148. package/temp_resend_cli/repo/src/commands/emails/receiving/attachment.ts +0 -55
  1149. package/temp_resend_cli/repo/src/commands/emails/receiving/attachments.ts +0 -68
  1150. package/temp_resend_cli/repo/src/commands/emails/receiving/get.ts +0 -58
  1151. package/temp_resend_cli/repo/src/commands/emails/receiving/index.ts +0 -28
  1152. package/temp_resend_cli/repo/src/commands/emails/receiving/list.ts +0 -59
  1153. package/temp_resend_cli/repo/src/commands/emails/receiving/utils.ts +0 -38
  1154. package/temp_resend_cli/repo/src/commands/emails/send.ts +0 -189
  1155. package/temp_resend_cli/repo/src/commands/open.ts +0 -27
  1156. package/temp_resend_cli/repo/src/commands/segments/create.ts +0 -50
  1157. package/temp_resend_cli/repo/src/commands/segments/delete.ts +0 -47
  1158. package/temp_resend_cli/repo/src/commands/segments/get.ts +0 -38
  1159. package/temp_resend_cli/repo/src/commands/segments/index.ts +0 -36
  1160. package/temp_resend_cli/repo/src/commands/segments/list.ts +0 -58
  1161. package/temp_resend_cli/repo/src/commands/segments/utils.ts +0 -7
  1162. package/temp_resend_cli/repo/src/commands/teams/index.ts +0 -10
  1163. package/temp_resend_cli/repo/src/commands/teams/list.ts +0 -35
  1164. package/temp_resend_cli/repo/src/commands/teams/remove.ts +0 -86
  1165. package/temp_resend_cli/repo/src/commands/teams/switch.ts +0 -76
  1166. package/temp_resend_cli/repo/src/commands/topics/create.ts +0 -73
  1167. package/temp_resend_cli/repo/src/commands/topics/delete.ts +0 -47
  1168. package/temp_resend_cli/repo/src/commands/topics/get.ts +0 -42
  1169. package/temp_resend_cli/repo/src/commands/topics/index.ts +0 -42
  1170. package/temp_resend_cli/repo/src/commands/topics/list.ts +0 -34
  1171. package/temp_resend_cli/repo/src/commands/topics/update.ts +0 -59
  1172. package/temp_resend_cli/repo/src/commands/topics/utils.ts +0 -16
  1173. package/temp_resend_cli/repo/src/commands/webhooks/create.ts +0 -128
  1174. package/temp_resend_cli/repo/src/commands/webhooks/delete.ts +0 -49
  1175. package/temp_resend_cli/repo/src/commands/webhooks/get.ts +0 -42
  1176. package/temp_resend_cli/repo/src/commands/webhooks/index.ts +0 -42
  1177. package/temp_resend_cli/repo/src/commands/webhooks/list.ts +0 -55
  1178. package/temp_resend_cli/repo/src/commands/webhooks/listen.ts +0 -379
  1179. package/temp_resend_cli/repo/src/commands/webhooks/update.ts +0 -83
  1180. package/temp_resend_cli/repo/src/commands/webhooks/utils.ts +0 -36
  1181. package/temp_resend_cli/repo/src/commands/whoami.ts +0 -71
  1182. package/temp_resend_cli/repo/src/lib/actions.ts +0 -157
  1183. package/temp_resend_cli/repo/src/lib/client.ts +0 -37
  1184. package/temp_resend_cli/repo/src/lib/config.ts +0 -217
  1185. package/temp_resend_cli/repo/src/lib/files.ts +0 -15
  1186. package/temp_resend_cli/repo/src/lib/help-text.ts +0 -38
  1187. package/temp_resend_cli/repo/src/lib/output.ts +0 -56
  1188. package/temp_resend_cli/repo/src/lib/pagination.ts +0 -36
  1189. package/temp_resend_cli/repo/src/lib/prompts.ts +0 -149
  1190. package/temp_resend_cli/repo/src/lib/spinner.ts +0 -100
  1191. package/temp_resend_cli/repo/src/lib/table.ts +0 -57
  1192. package/temp_resend_cli/repo/src/lib/tty.ts +0 -28
  1193. package/temp_resend_cli/repo/src/lib/update-check.ts +0 -169
  1194. package/temp_resend_cli/repo/src/lib/version.ts +0 -4
  1195. package/temp_resend_cli/repo/tests/commands/api-keys/create.test.ts +0 -196
  1196. package/temp_resend_cli/repo/tests/commands/api-keys/delete.test.ts +0 -157
  1197. package/temp_resend_cli/repo/tests/commands/api-keys/list.test.ts +0 -134
  1198. package/temp_resend_cli/repo/tests/commands/auth/login.test.ts +0 -153
  1199. package/temp_resend_cli/repo/tests/commands/auth/logout.test.ts +0 -153
  1200. package/temp_resend_cli/repo/tests/commands/broadcasts/create.test.ts +0 -454
  1201. package/temp_resend_cli/repo/tests/commands/broadcasts/delete.test.ts +0 -183
  1202. package/temp_resend_cli/repo/tests/commands/broadcasts/get.test.ts +0 -147
  1203. package/temp_resend_cli/repo/tests/commands/broadcasts/list.test.ts +0 -199
  1204. package/temp_resend_cli/repo/tests/commands/broadcasts/send.test.ts +0 -162
  1205. package/temp_resend_cli/repo/tests/commands/broadcasts/update.test.ts +0 -288
  1206. package/temp_resend_cli/repo/tests/commands/contact-properties/create.test.ts +0 -251
  1207. package/temp_resend_cli/repo/tests/commands/contact-properties/delete.test.ts +0 -184
  1208. package/temp_resend_cli/repo/tests/commands/contact-properties/get.test.ts +0 -145
  1209. package/temp_resend_cli/repo/tests/commands/contact-properties/list.test.ts +0 -181
  1210. package/temp_resend_cli/repo/tests/commands/contact-properties/update.test.ts +0 -217
  1211. package/temp_resend_cli/repo/tests/commands/contacts/add-segment.test.ts +0 -189
  1212. package/temp_resend_cli/repo/tests/commands/contacts/create.test.ts +0 -271
  1213. package/temp_resend_cli/repo/tests/commands/contacts/delete.test.ts +0 -193
  1214. package/temp_resend_cli/repo/tests/commands/contacts/get.test.ts +0 -149
  1215. package/temp_resend_cli/repo/tests/commands/contacts/list.test.ts +0 -176
  1216. package/temp_resend_cli/repo/tests/commands/contacts/remove-segment.test.ts +0 -167
  1217. package/temp_resend_cli/repo/tests/commands/contacts/segments.test.ts +0 -168
  1218. package/temp_resend_cli/repo/tests/commands/contacts/topics.test.ts +0 -164
  1219. package/temp_resend_cli/repo/tests/commands/contacts/update-topics.test.ts +0 -248
  1220. package/temp_resend_cli/repo/tests/commands/contacts/update.test.ts +0 -206
  1221. package/temp_resend_cli/repo/tests/commands/doctor.test.ts +0 -164
  1222. package/temp_resend_cli/repo/tests/commands/domains/create.test.ts +0 -193
  1223. package/temp_resend_cli/repo/tests/commands/domains/delete.test.ts +0 -157
  1224. package/temp_resend_cli/repo/tests/commands/domains/get.test.ts +0 -138
  1225. package/temp_resend_cli/repo/tests/commands/domains/list.test.ts +0 -165
  1226. package/temp_resend_cli/repo/tests/commands/domains/update.test.ts +0 -224
  1227. package/temp_resend_cli/repo/tests/commands/domains/verify.test.ts +0 -118
  1228. package/temp_resend_cli/repo/tests/commands/emails/batch.test.ts +0 -324
  1229. package/temp_resend_cli/repo/tests/commands/emails/get.test.ts +0 -132
  1230. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachment.test.ts +0 -141
  1231. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachments.test.ts +0 -169
  1232. package/temp_resend_cli/repo/tests/commands/emails/receiving/get.test.ts +0 -141
  1233. package/temp_resend_cli/repo/tests/commands/emails/receiving/list.test.ts +0 -182
  1234. package/temp_resend_cli/repo/tests/commands/emails/send.test.ts +0 -312
  1235. package/temp_resend_cli/repo/tests/commands/segments/create.test.ts +0 -164
  1236. package/temp_resend_cli/repo/tests/commands/segments/delete.test.ts +0 -183
  1237. package/temp_resend_cli/repo/tests/commands/segments/get.test.ts +0 -138
  1238. package/temp_resend_cli/repo/tests/commands/segments/list.test.ts +0 -174
  1239. package/temp_resend_cli/repo/tests/commands/teams/list.test.ts +0 -62
  1240. package/temp_resend_cli/repo/tests/commands/teams/remove.test.ts +0 -110
  1241. package/temp_resend_cli/repo/tests/commands/teams/switch.test.ts +0 -103
  1242. package/temp_resend_cli/repo/tests/commands/topics/create.test.ts +0 -192
  1243. package/temp_resend_cli/repo/tests/commands/topics/delete.test.ts +0 -157
  1244. package/temp_resend_cli/repo/tests/commands/topics/get.test.ts +0 -126
  1245. package/temp_resend_cli/repo/tests/commands/topics/list.test.ts +0 -125
  1246. package/temp_resend_cli/repo/tests/commands/topics/update.test.ts +0 -178
  1247. package/temp_resend_cli/repo/tests/commands/webhooks/create.test.ts +0 -225
  1248. package/temp_resend_cli/repo/tests/commands/webhooks/delete.test.ts +0 -157
  1249. package/temp_resend_cli/repo/tests/commands/webhooks/get.test.ts +0 -126
  1250. package/temp_resend_cli/repo/tests/commands/webhooks/list.test.ts +0 -178
  1251. package/temp_resend_cli/repo/tests/commands/webhooks/update.test.ts +0 -207
  1252. package/temp_resend_cli/repo/tests/commands/whoami.test.ts +0 -98
  1253. package/temp_resend_cli/repo/tests/e2e/smoke.test.ts +0 -93
  1254. package/temp_resend_cli/repo/tests/helpers.ts +0 -86
  1255. package/temp_resend_cli/repo/tests/lib/client.test.ts +0 -71
  1256. package/temp_resend_cli/repo/tests/lib/config.test.ts +0 -451
  1257. package/temp_resend_cli/repo/tests/lib/files.test.ts +0 -73
  1258. package/temp_resend_cli/repo/tests/lib/help-text.test.ts +0 -97
  1259. package/temp_resend_cli/repo/tests/lib/output.test.ts +0 -136
  1260. package/temp_resend_cli/repo/tests/lib/prompts.test.ts +0 -185
  1261. package/temp_resend_cli/repo/tests/lib/spinner.test.ts +0 -166
  1262. package/temp_resend_cli/repo/tests/lib/table.test.ts +0 -63
  1263. package/temp_resend_cli/repo/tests/lib/tty.test.ts +0 -89
  1264. package/temp_resend_cli/repo/tests/lib/update-check.test.ts +0 -179
  1265. package/temp_resend_cli/repo/tsconfig.json +0 -14
  1266. package/temp_resend_cli/repo/vitest.config.e2e.ts +0 -8
  1267. package/temp_resend_cli/repo/vitest.config.ts +0 -10
  1268. /package/docs/{plugin-examples.md → plugins-examples.md} +0 -0
@@ -1,2051 +0,0 @@
1
- /// Python string type, wrapping a Rust `String`.
2
- ///
3
- /// This type provides Python string semantics. Currently supports basic
4
- /// operations like length and equality comparison.
5
- use std::{borrow::Cow, fmt};
6
- use std::{cmp::Ordering, fmt::Write};
7
-
8
- use ahash::AHashSet;
9
- use smallvec::smallvec;
10
-
11
- use super::{Bytes, MontyIter, PyTrait};
12
- use crate::{
13
- args::ArgValues,
14
- bytecode::{CallResult, VM},
15
- defer_drop, defer_drop_mut,
16
- exception_private::{ExcType, RunResult},
17
- heap::{DropWithHeap, Heap, HeapData, HeapGuard, HeapId},
18
- intern::{StaticStrings, StringId},
19
- resource::{ResourceError, ResourceTracker, check_repeat_size, check_replace_size},
20
- types::Type,
21
- value::{EitherStr, Value},
22
- };
23
-
24
- /// Python string value stored on the heap.
25
- ///
26
- /// Wraps a Rust `String` and provides Python-compatible operations.
27
- /// `len()` returns the number of Unicode codepoints (characters), matching Python semantics.
28
- #[derive(Debug, Clone, PartialEq, Default, serde::Serialize, serde::Deserialize)]
29
- pub(crate) struct Str(Box<str>);
30
-
31
- impl Str {
32
- /// Creates a new Str from a Rust String.
33
- #[must_use]
34
- pub fn new(s: String) -> Self {
35
- Self(s.into())
36
- }
37
-
38
- /// Returns a reference to the inner string.
39
- #[must_use]
40
- pub fn as_str(&self) -> &str {
41
- &self.0
42
- }
43
-
44
- /// Creates a string from the `str()` constructor call.
45
- ///
46
- /// - `str()` with no args returns an empty string
47
- /// - `str(x)` converts x to its string representation using `py_str`
48
- pub fn init(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
49
- let value = args.get_zero_one_arg("str", vm.heap)?;
50
- match value {
51
- None => Ok(Value::InternString(StaticStrings::EmptyString.into())),
52
- Some(v) => {
53
- defer_drop!(v, vm);
54
- let s = v.py_str(vm).into_owned();
55
- allocate_string(s, vm.heap)
56
- }
57
- }
58
- }
59
-
60
- /// Handles slice-based indexing for strings.
61
- ///
62
- /// Returns a new string containing the selected characters (Unicode-aware).
63
- fn getitem_slice(&self, slice: &crate::types::Slice, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
64
- let char_count = self.0.chars().count();
65
- let (start, stop, step) = slice
66
- .indices(char_count)
67
- .map_err(|()| ExcType::value_error_slice_step_zero())?;
68
-
69
- let result_str = get_str_slice(&self.0, start, stop, step);
70
- let heap_id = heap.allocate(HeapData::Str(Self::from(result_str)))?;
71
- Ok(Value::Ref(heap_id))
72
- }
73
- }
74
-
75
- impl From<String> for Str {
76
- fn from(s: String) -> Self {
77
- Self(s.into())
78
- }
79
- }
80
-
81
- impl From<&str> for Str {
82
- fn from(s: &str) -> Self {
83
- Self(s.into())
84
- }
85
- }
86
-
87
- impl From<Str> for String {
88
- fn from(value: Str) -> Self {
89
- value.0.into_string()
90
- }
91
- }
92
-
93
- /// Allocates a string, using interned versions when possible.
94
- ///
95
- /// Optimizations:
96
- /// - Empty strings return the pre-interned `StaticStrings::EmptyString`
97
- /// - Single ASCII characters return pre-interned ASCII strings
98
- /// - Other strings are allocated on the heap
99
- ///
100
- /// This avoids heap allocation for common cases like results from `strip()`,
101
- /// `split()`, string iteration, etc.
102
- pub fn allocate_string(s: String, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
103
- match s.len() {
104
- 0 => Ok(Value::InternString(StaticStrings::EmptyString.into())),
105
- 1 => {
106
- // Single byte means single ASCII character
107
- let byte = s.as_bytes()[0];
108
- Ok(Value::InternString(StringId::from_ascii(byte)))
109
- }
110
- _ => {
111
- let heap_id = heap.allocate(HeapData::Str(Str::new(s)))?;
112
- Ok(Value::Ref(heap_id))
113
- }
114
- }
115
- }
116
-
117
- /// Allocates a single character as a string value.
118
- ///
119
- /// ASCII characters use pre-interned strings for efficiency.
120
- /// Non-ASCII characters are allocated on the heap.
121
- ///
122
- /// This is used by string iteration and `chr()` builtin.
123
- pub fn allocate_char(c: char, heap: &mut Heap<impl ResourceTracker>) -> Result<Value, ResourceError> {
124
- if c.is_ascii() {
125
- Ok(Value::InternString(StringId::from_ascii(c as u8)))
126
- } else {
127
- let heap_id = heap.allocate(HeapData::Str(Str::new(c.to_string())))?;
128
- Ok(Value::Ref(heap_id))
129
- }
130
- }
131
-
132
- /// Gets the character at a given index in a string, handling negative indices.
133
- ///
134
- /// Returns `None` if the index is out of bounds. This uses a single-pass scan
135
- /// to avoid allocating a `Vec<char>`.
136
- ///
137
- /// Negative indices count from the end: -1 is the last character.
138
- pub fn get_char_at_index(s: &str, index: i64) -> Option<char> {
139
- let char_count = s.chars().count();
140
- let len = i64::try_from(char_count).ok()?;
141
- let normalized = if index < 0 { index + len } else { index };
142
-
143
- if normalized < 0 || normalized >= len {
144
- return None;
145
- }
146
-
147
- let idx = usize::try_from(normalized).ok()?;
148
- s.chars().nth(idx)
149
- }
150
-
151
- /// Extracts a slice of a string (Unicode-aware).
152
- ///
153
- /// Handles both positive and negative step values. For negative step,
154
- /// iterates backward from start down to (but not including) stop.
155
- /// The `stop` parameter uses a sentinel value of `len + 1` for negative
156
- /// step to indicate "go to the beginning".
157
- ///
158
- /// Note: step must be non-zero (callers should validate this via `slice.indices()`).
159
- pub(crate) fn get_str_slice(s: &str, start: usize, stop: usize, step: i64) -> String {
160
- let chars: Vec<char> = s.chars().collect();
161
- let mut result = String::new();
162
-
163
- // try_from succeeds for non-negative step; step==0 rejected upstream by slice.indices()
164
- if let Ok(step_usize) = usize::try_from(step) {
165
- // Positive step: iterate forward
166
- let mut i = start;
167
- while i < stop && i < chars.len() {
168
- result.push(chars[i]);
169
- i += step_usize;
170
- }
171
- } else {
172
- // Negative step: iterate backward
173
- // start is the highest index, stop is the sentinel
174
- // stop > chars.len() means "go to the beginning"
175
- let step_abs = usize::try_from(-step).expect("step is negative so -step is positive");
176
- let step_abs_i64 = i64::try_from(step_abs).expect("step magnitude fits in i64");
177
- let mut i = i64::try_from(start).expect("start index fits in i64");
178
- // stop > chars.len() is sentinel meaning "go to beginning", use -1
179
- let stop_i64 = if stop > chars.len() {
180
- -1
181
- } else {
182
- i64::try_from(stop).expect("stop bounded by chars.len() fits in i64")
183
- };
184
-
185
- while let Ok(i_usize) = usize::try_from(i) {
186
- if i_usize >= chars.len() || i <= stop_i64 {
187
- break;
188
- }
189
- result.push(chars[i_usize]);
190
- i -= step_abs_i64;
191
- }
192
- }
193
-
194
- result
195
- }
196
-
197
- impl std::ops::Deref for Str {
198
- type Target = str;
199
-
200
- fn deref(&self) -> &Self::Target {
201
- &self.0
202
- }
203
- }
204
-
205
- impl PyTrait for Str {
206
- fn py_type(&self, _heap: &Heap<impl ResourceTracker>) -> Type {
207
- Type::Str
208
- }
209
-
210
- fn py_estimate_size(&self) -> usize {
211
- std::mem::size_of::<Self>() + self.0.len()
212
- }
213
-
214
- fn py_len(&self, _vm: &VM<'_, '_, impl ResourceTracker>) -> Option<usize> {
215
- // Count Unicode characters, not bytes, to match Python semantics
216
- Some(self.0.chars().count())
217
- }
218
-
219
- fn py_getitem(&self, key: &Value, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
220
- let heap = &mut *vm.heap;
221
- // Check for slice first (Value::Ref pointing to HeapData::Slice)
222
- if let Value::Ref(id) = key
223
- && let HeapData::Slice(slice) = heap.get(*id)
224
- {
225
- // Clone the slice to release the borrow on heap before calling getitem_slice
226
- let slice = slice.clone();
227
- return self.getitem_slice(&slice, heap);
228
- }
229
-
230
- // Extract integer index, accepting Int, Bool (True=1, False=0), and LongInt
231
- let index = key.as_index(heap, Type::Str)?;
232
-
233
- // Use single-pass indexing to avoid Vec<char> allocation
234
- let c = get_char_at_index(&self.0, index).ok_or_else(ExcType::str_index_error)?;
235
- Ok(allocate_char(c, heap)?)
236
- }
237
-
238
- fn py_eq(&self, other: &Self, _vm: &mut VM<'_, '_, impl ResourceTracker>) -> Result<bool, ResourceError> {
239
- Ok(self.0 == other.0)
240
- }
241
-
242
- /// Interns don't contain nested heap references.
243
- fn py_dec_ref_ids(&mut self, _stack: &mut Vec<HeapId>) {
244
- // No-op: strings don't hold Value references
245
- }
246
-
247
- fn py_bool(&self, _vm: &VM<'_, '_, impl ResourceTracker>) -> bool {
248
- !self.0.is_empty()
249
- }
250
-
251
- fn py_cmp(
252
- &self,
253
- other: &Self,
254
- _vm: &mut VM<'_, '_, impl ResourceTracker>,
255
- ) -> Result<Option<Ordering>, ResourceError> {
256
- Ok(Some(self.0.cmp(&other.0)))
257
- }
258
-
259
- fn py_repr_fmt(
260
- &self,
261
- f: &mut impl Write,
262
- _vm: &VM<'_, '_, impl ResourceTracker>,
263
- _heap_ids: &mut AHashSet<HeapId>,
264
- ) -> fmt::Result {
265
- string_repr_fmt(&self.0, f)
266
- }
267
-
268
- fn py_str(&self, _vm: &VM<'_, '_, impl ResourceTracker>) -> Cow<'static, str> {
269
- self.0.clone().into_string().into()
270
- }
271
-
272
- fn py_add(
273
- &self,
274
- other: &Self,
275
- vm: &mut VM<'_, '_, impl ResourceTracker>,
276
- ) -> Result<Option<Value>, crate::resource::ResourceError> {
277
- let result = format!("{}{}", self.0, other.0);
278
- let id = vm.heap.allocate(HeapData::Str(result.into()))?;
279
- Ok(Some(Value::Ref(id)))
280
- }
281
-
282
- fn py_call_attr(
283
- &mut self,
284
- _self_id: HeapId,
285
- vm: &mut VM<'_, '_, impl ResourceTracker>,
286
- attr: &EitherStr,
287
- args: ArgValues,
288
- ) -> RunResult<CallResult> {
289
- let args_guard = HeapGuard::new(args, vm.heap);
290
- let Some(method) = attr.static_string() else {
291
- return Err(ExcType::attribute_error(Type::Str, attr.as_str(vm.interns)));
292
- };
293
-
294
- let args = args_guard.into_inner();
295
- call_str_method_impl(&self.0, method, args, vm).map(CallResult::Value)
296
- }
297
- }
298
-
299
- /// Dispatches a method call on a string value by method name.
300
- ///
301
- /// This is the entry point for string method calls from the VM on interned strings.
302
- /// Converts the `StringId` to `StaticStrings` and delegates to `call_str_method_impl`.
303
- pub fn call_str_method(
304
- s: &str,
305
- method_id: StringId,
306
- args: ArgValues,
307
- vm: &mut VM<'_, '_, impl ResourceTracker>,
308
- ) -> RunResult<Value> {
309
- let args_guard = HeapGuard::new(args, vm.heap);
310
- let Some(method) = StaticStrings::from_string_id(method_id) else {
311
- return Err(ExcType::attribute_error(Type::Str, vm.interns.get_str(method_id)));
312
- };
313
- let args = args_guard.into_inner();
314
- call_str_method_impl(s, method, args, vm)
315
- }
316
-
317
- /// Dispatches a method call on a string value.
318
- ///
319
- /// This is the unified implementation for string method calls, used by both:
320
- /// - `Str::py_call_attr()` for heap-allocated strings
321
- /// - `call_str_method()` for interned string literals from the VM
322
- ///
323
- /// # Not Yet Implemented
324
- ///
325
- /// The following Python string methods are not yet implemented:
326
- ///
327
- /// - `format()` - Requires implementing the format spec mini-language (PEP 3101),
328
- /// which is complex and involves parsing format specifications like `{:>10.2f}`.
329
- /// - `format_map(mapping)` - Similar to `format()` but takes a mapping; depends on
330
- /// `format()` implementation.
331
- /// - `maketrans()` / `translate()` - Character translation tables; moderate complexity,
332
- /// requires building and applying Unicode translation maps.
333
- /// - `expandtabs(tabsize=8)` - Tab expansion; simple but rarely used in practice.
334
- /// - `isprintable()` - Checks if all characters are printable; requires accurate Unicode
335
- /// category data for the "printable" property.
336
- fn call_str_method_impl(
337
- s: &str,
338
- method: StaticStrings,
339
- args: ArgValues,
340
- vm: &mut VM<'_, '_, impl ResourceTracker>,
341
- ) -> RunResult<Value> {
342
- match method {
343
- // Simple transformations (no arguments)
344
- StaticStrings::Lower => {
345
- args.check_zero_args("str.lower", vm.heap)?;
346
- str_lower(s, vm.heap)
347
- }
348
- StaticStrings::Upper => {
349
- args.check_zero_args("str.upper", vm.heap)?;
350
- str_upper(s, vm.heap)
351
- }
352
- StaticStrings::Capitalize => {
353
- args.check_zero_args("str.capitalize", vm.heap)?;
354
- str_capitalize(s, vm.heap)
355
- }
356
- StaticStrings::Title => {
357
- args.check_zero_args("str.title", vm.heap)?;
358
- str_title(s, vm.heap)
359
- }
360
- StaticStrings::Swapcase => {
361
- args.check_zero_args("str.swapcase", vm.heap)?;
362
- str_swapcase(s, vm.heap)
363
- }
364
- StaticStrings::Casefold => {
365
- args.check_zero_args("str.casefold", vm.heap)?;
366
- str_casefold(s, vm.heap)
367
- }
368
- // Predicate methods (no arguments, return bool)
369
- StaticStrings::Isalpha => {
370
- args.check_zero_args("str.isalpha", vm.heap)?;
371
- Ok(Value::Bool(str_isalpha(s)))
372
- }
373
- StaticStrings::Isdigit => {
374
- args.check_zero_args("str.isdigit", vm.heap)?;
375
- Ok(Value::Bool(str_isdigit(s)))
376
- }
377
- StaticStrings::Isalnum => {
378
- args.check_zero_args("str.isalnum", vm.heap)?;
379
- Ok(Value::Bool(str_isalnum(s)))
380
- }
381
- StaticStrings::Isnumeric => {
382
- args.check_zero_args("str.isnumeric", vm.heap)?;
383
- Ok(Value::Bool(str_isnumeric(s)))
384
- }
385
- StaticStrings::Isspace => {
386
- args.check_zero_args("str.isspace", vm.heap)?;
387
- Ok(Value::Bool(str_isspace(s)))
388
- }
389
- StaticStrings::Islower => {
390
- args.check_zero_args("str.islower", vm.heap)?;
391
- Ok(Value::Bool(str_islower(s)))
392
- }
393
- StaticStrings::Isupper => {
394
- args.check_zero_args("str.isupper", vm.heap)?;
395
- Ok(Value::Bool(str_isupper(s)))
396
- }
397
- StaticStrings::Isascii => {
398
- args.check_zero_args("str.isascii", vm.heap)?;
399
- Ok(Value::Bool(s.is_ascii()))
400
- }
401
- StaticStrings::Isdecimal => {
402
- args.check_zero_args("str.isdecimal", vm.heap)?;
403
- Ok(Value::Bool(str_isdecimal(s)))
404
- }
405
- // Search methods
406
- StaticStrings::Find => str_find(s, args, vm),
407
- StaticStrings::Rfind => str_rfind(s, args, vm),
408
- StaticStrings::Index => str_index(s, args, vm),
409
- StaticStrings::Rindex => str_rindex(s, args, vm),
410
- StaticStrings::Count => str_count(s, args, vm),
411
- StaticStrings::Startswith => str_startswith(s, args, vm),
412
- StaticStrings::Endswith => str_endswith(s, args, vm),
413
- // Strip/trim methods
414
- StaticStrings::Strip => str_strip(s, args, vm),
415
- StaticStrings::Lstrip => str_lstrip(s, args, vm),
416
- StaticStrings::Rstrip => str_rstrip(s, args, vm),
417
- StaticStrings::Removeprefix => str_removeprefix(s, args, vm),
418
- StaticStrings::Removesuffix => str_removesuffix(s, args, vm),
419
- // Split methods
420
- StaticStrings::Split => str_split(s, args, vm),
421
- StaticStrings::Rsplit => str_rsplit(s, args, vm),
422
- StaticStrings::Splitlines => str_splitlines(s, args, vm),
423
- StaticStrings::Partition => str_partition(s, args, vm),
424
- StaticStrings::Rpartition => str_rpartition(s, args, vm),
425
- // Replace/modify methods
426
- StaticStrings::Replace => str_replace(s, args, vm),
427
- StaticStrings::Center => str_center(s, args, vm),
428
- StaticStrings::Ljust => str_ljust(s, args, vm),
429
- StaticStrings::Rjust => str_rjust(s, args, vm),
430
- StaticStrings::Zfill => str_zfill(s, args, vm.heap),
431
- // Additional methods
432
- StaticStrings::Encode => str_encode(s, args, vm),
433
- StaticStrings::Isidentifier => {
434
- args.check_zero_args("str.isidentifier", vm.heap)?;
435
- Ok(Value::Bool(str_isidentifier(s)))
436
- }
437
- StaticStrings::Istitle => {
438
- args.check_zero_args("str.istitle", vm.heap)?;
439
- Ok(Value::Bool(str_istitle(s)))
440
- }
441
- // Existing method
442
- StaticStrings::Join => {
443
- let iterable = args.get_one_arg("str.join", vm.heap)?;
444
- str_join(s, iterable, vm)
445
- }
446
- _ => {
447
- args.drop_with_heap(vm.heap);
448
- Err(ExcType::attribute_error(Type::Str, method.into()))
449
- }
450
- }
451
- }
452
-
453
- /// Implements Python's `str.join(iterable)` method.
454
- ///
455
- /// Joins elements of the iterable with the separator string, returning
456
- /// a new heap-allocated string. Each element must be a string.
457
- ///
458
- /// # Arguments
459
- /// * `separator` - The separator string (e.g., "," for comma-separated)
460
- /// * `iterable` - The iterable containing string elements to join
461
- /// * `heap` - The heap for allocation and reference counting
462
- /// * `interns` - The interns table for resolving interned strings
463
- ///
464
- /// # Errors
465
- /// Returns `TypeError` if the argument is not iterable or if any element is not a string.
466
- fn str_join(separator: &str, iterable: Value, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
467
- // Create MontyIter from the iterable, with join-specific error message
468
- let Ok(iter) = MontyIter::new(iterable, vm) else {
469
- return Err(ExcType::type_error_join_not_iterable());
470
- };
471
- defer_drop_mut!(iter, vm);
472
-
473
- // Build result string, tracking index for error messages
474
- let mut result = String::new();
475
- let mut index = 0usize;
476
-
477
- while let Some(item) = iter.for_next(vm)? {
478
- defer_drop!(item, vm);
479
- if index > 0 {
480
- result.push_str(separator);
481
- }
482
-
483
- // Check item is a string and extract its content
484
- match item {
485
- Value::InternString(id) => {
486
- result.push_str(vm.interns.get_str(*id));
487
- }
488
- Value::Ref(heap_id) => {
489
- if let HeapData::Str(s) = vm.heap.get(*heap_id) {
490
- result.push_str(s.as_str());
491
- } else {
492
- let t = item.py_type(vm.heap);
493
- return Err(ExcType::type_error_join_item(index, t));
494
- }
495
- }
496
- _ => {
497
- let t = item.py_type(vm.heap);
498
- return Err(ExcType::type_error_join_item(index, t));
499
- }
500
- }
501
- index += 1;
502
- }
503
-
504
- // Allocate result (uses interned empty string if result is empty)
505
- allocate_string(result, vm.heap)
506
- }
507
-
508
- /// Writes a Python repr() string for a given string slice to a formatter.
509
- ///
510
- /// Chooses between single and double quotes based on the string content:
511
- /// - Uses double quotes if the string contains single quotes but not double quotes
512
- /// - Uses single quotes by default, escaping any contained single quotes
513
- ///
514
- /// Common escape sequences (backslash, newline, tab, carriage return) are always escaped.
515
- pub fn string_repr_fmt(s: &str, f: &mut impl Write) -> fmt::Result {
516
- // Check if the string contains single quotes but not double quotes
517
- if s.contains('\'') && !s.contains('"') {
518
- // Use double quotes if string contains only single quotes
519
- f.write_char('"')?;
520
- for c in s.chars() {
521
- match c {
522
- '\\' => f.write_str("\\\\")?,
523
- '\n' => f.write_str("\\n")?,
524
- '\t' => f.write_str("\\t")?,
525
- '\r' => f.write_str("\\r")?,
526
- _ => f.write_char(c)?,
527
- }
528
- }
529
- f.write_char('"')
530
- } else {
531
- // Use single quotes by default, escape any single quotes in the string
532
- f.write_char('\'')?;
533
- for c in s.chars() {
534
- match c {
535
- '\\' => f.write_str("\\\\")?,
536
- '\n' => f.write_str("\\n")?,
537
- '\t' => f.write_str("\\t")?,
538
- '\r' => f.write_str("\\r")?,
539
- '\'' => f.write_str("\\'")?,
540
- _ => f.write_char(c)?,
541
- }
542
- }
543
- f.write_char('\'')
544
- }
545
- }
546
-
547
- /// Formatter for a Python repr() string.
548
- #[derive(Debug)]
549
- pub struct StringRepr<'a>(pub &'a str);
550
-
551
- impl fmt::Display for StringRepr<'_> {
552
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553
- string_repr_fmt(self.0, f)
554
- }
555
- }
556
-
557
- // =============================================================================
558
- // Simple transformations (no arguments)
559
- // =============================================================================
560
-
561
- /// Implements Python's `str.lower()` method.
562
- fn str_lower(s: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
563
- allocate_string(s.to_lowercase(), heap)
564
- }
565
-
566
- /// Implements Python's `str.upper()` method.
567
- fn str_upper(s: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
568
- allocate_string(s.to_uppercase(), heap)
569
- }
570
-
571
- /// Implements Python's `str.capitalize()` method.
572
- ///
573
- /// Returns a copy of the string with its first character capitalized and the rest lowercased.
574
- fn str_capitalize(s: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
575
- let mut chars = s.chars();
576
- let result = match chars.next() {
577
- None => String::new(),
578
- Some(first) => {
579
- let mut result = first.to_uppercase().to_string();
580
- for c in chars {
581
- result.extend(c.to_lowercase());
582
- }
583
- result
584
- }
585
- };
586
- allocate_string(result, heap)
587
- }
588
-
589
- /// Implements Python's `str.title()` method.
590
- ///
591
- /// Returns a titlecased version of the string where words start with an uppercase
592
- /// character and the remaining characters are lowercase.
593
- fn str_title(s: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
594
- let mut result = String::with_capacity(s.len());
595
- let mut prev_is_cased = false;
596
-
597
- for c in s.chars() {
598
- if prev_is_cased {
599
- result.extend(c.to_lowercase());
600
- } else {
601
- result.extend(c.to_uppercase());
602
- }
603
- prev_is_cased = c.is_alphabetic();
604
- }
605
-
606
- allocate_string(result, heap)
607
- }
608
-
609
- /// Implements Python's `str.swapcase()` method.
610
- ///
611
- /// Returns a copy of the string with uppercase characters converted to lowercase and vice versa.
612
- fn str_swapcase(s: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
613
- let mut result = String::with_capacity(s.len());
614
-
615
- for c in s.chars() {
616
- if c.is_uppercase() {
617
- result.extend(c.to_lowercase());
618
- } else if c.is_lowercase() {
619
- result.extend(c.to_uppercase());
620
- } else {
621
- result.push(c);
622
- }
623
- }
624
-
625
- allocate_string(result, heap)
626
- }
627
-
628
- /// Implements Python's `str.casefold()` method.
629
- ///
630
- /// Returns a casefolded copy of the string. Casefolding is similar to lowercasing
631
- /// but more aggressive because it is intended for caseless string matching.
632
- fn str_casefold(s: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
633
- // Rust's to_lowercase() is equivalent to Unicode casefolding for most purposes
634
- allocate_string(s.to_lowercase(), heap)
635
- }
636
-
637
- // =============================================================================
638
- // Predicate methods (no arguments, return bool)
639
- // =============================================================================
640
-
641
- /// Implements Python's `str.isalpha()` method.
642
- ///
643
- /// Returns True if all characters in the string are alphabetic and there is at least one character.
644
- fn str_isalpha(s: &str) -> bool {
645
- !s.is_empty() && s.chars().all(char::is_alphabetic)
646
- }
647
-
648
- /// Implements Python's `str.isdigit()` method.
649
- ///
650
- /// Returns True if all characters in the string are digits and there is at least one character.
651
- /// In Python, digits include decimal digits (Nd) plus characters with Numeric_Type=Digit
652
- /// (superscripts, subscripts, circled digits, etc.).
653
- fn str_isdigit(s: &str) -> bool {
654
- !s.is_empty() && s.chars().all(is_unicode_digit)
655
- }
656
-
657
- /// Implements Python's `str.isalnum()` method.
658
- ///
659
- /// Returns True if all characters in the string are alphanumeric and there is at least one character.
660
- fn str_isalnum(s: &str) -> bool {
661
- !s.is_empty() && s.chars().all(char::is_alphanumeric)
662
- }
663
-
664
- /// Implements Python's `str.isnumeric()` method.
665
- ///
666
- /// Returns True if all characters in the string are numeric and there is at least one character.
667
- /// In Python, numeric includes decimal digits (Nd), letter numerals (Nl), and other numerals (No).
668
- /// Rust's `char::is_numeric()` checks for all of these categories.
669
- fn str_isnumeric(s: &str) -> bool {
670
- !s.is_empty() && s.chars().all(char::is_numeric)
671
- }
672
-
673
- /// Implements Python's `str.isspace()` method.
674
- ///
675
- /// Returns True if all characters in the string are whitespace and there is at least one character.
676
- fn str_isspace(s: &str) -> bool {
677
- !s.is_empty() && s.chars().all(char::is_whitespace)
678
- }
679
-
680
- /// Implements Python's `str.islower()` method.
681
- ///
682
- /// Returns True if all cased characters in the string are lowercase and there is at least one cased character.
683
- fn str_islower(s: &str) -> bool {
684
- let mut has_cased = false;
685
- for c in s.chars() {
686
- if c.is_uppercase() {
687
- return false;
688
- }
689
- if c.is_lowercase() {
690
- has_cased = true;
691
- }
692
- }
693
- has_cased
694
- }
695
-
696
- /// Implements Python's `str.isupper()` method.
697
- ///
698
- /// Returns True if all cased characters in the string are uppercase and there is at least one cased character.
699
- fn str_isupper(s: &str) -> bool {
700
- let mut has_cased = false;
701
- for c in s.chars() {
702
- if c.is_lowercase() {
703
- return false;
704
- }
705
- if c.is_uppercase() {
706
- has_cased = true;
707
- }
708
- }
709
- has_cased
710
- }
711
-
712
- /// Implements Python's `str.isdecimal()` method.
713
- ///
714
- /// Returns True if all characters in the string are decimal characters and there is at least one character.
715
- /// Decimal characters are those in Unicode category Nd (Decimal_Number) - digits that can be used
716
- /// to form numbers in base 10.
717
- fn str_isdecimal(s: &str) -> bool {
718
- !s.is_empty() && s.chars().all(is_unicode_decimal)
719
- }
720
-
721
- /// Checks if a character is a Unicode decimal digit (Nd category).
722
- ///
723
- /// This covers decimal digit ranges from various scripts including ASCII, Arabic-Indic,
724
- /// Devanagari, Bengali, Thai, Fullwidth, and many others.
725
- fn is_unicode_decimal(c: char) -> bool {
726
- let cp = c as u32;
727
- matches!(
728
- cp,
729
- // Basic Latin (ASCII digits)
730
- 0x0030..=0x0039
731
- // Arabic-Indic digits
732
- | 0x0660..=0x0669
733
- // Extended Arabic-Indic digits
734
- | 0x06F0..=0x06F9
735
- // NKo digits
736
- | 0x07C0..=0x07C9
737
- // Devanagari digits
738
- | 0x0966..=0x096F
739
- // Bengali digits
740
- | 0x09E6..=0x09EF
741
- // Gurmukhi digits
742
- | 0x0A66..=0x0A6F
743
- // Gujarati digits
744
- | 0x0AE6..=0x0AEF
745
- // Oriya digits
746
- | 0x0B66..=0x0B6F
747
- // Tamil digits
748
- | 0x0BE6..=0x0BEF
749
- // Telugu digits
750
- | 0x0C66..=0x0C6F
751
- // Kannada digits
752
- | 0x0CE6..=0x0CEF
753
- // Malayalam digits
754
- | 0x0D66..=0x0D6F
755
- // Sinhala Lith digits
756
- | 0x0DE6..=0x0DEF
757
- // Thai digits
758
- | 0x0E50..=0x0E59
759
- // Lao digits
760
- | 0x0ED0..=0x0ED9
761
- // Tibetan digits
762
- | 0x0F20..=0x0F29
763
- // Myanmar digits
764
- | 0x1040..=0x1049
765
- // Myanmar Shan digits
766
- | 0x1090..=0x1099
767
- // Khmer digits
768
- | 0x17E0..=0x17E9
769
- // Mongolian digits
770
- | 0x1810..=0x1819
771
- // Limbu digits
772
- | 0x1946..=0x194F
773
- // New Tai Lue digits
774
- | 0x19D0..=0x19D9
775
- // Tai Tham Hora digits
776
- | 0x1A80..=0x1A89
777
- // Tai Tham Tham digits
778
- | 0x1A90..=0x1A99
779
- // Balinese digits
780
- | 0x1B50..=0x1B59
781
- // Sundanese digits
782
- | 0x1BB0..=0x1BB9
783
- // Lepcha digits
784
- | 0x1C40..=0x1C49
785
- // Ol Chiki digits
786
- | 0x1C50..=0x1C59
787
- // Vai digits
788
- | 0xA620..=0xA629
789
- // Saurashtra digits
790
- | 0xA8D0..=0xA8D9
791
- // Kayah Li digits
792
- | 0xA900..=0xA909
793
- // Javanese digits
794
- | 0xA9D0..=0xA9D9
795
- // Myanmar Tai Laing digits
796
- | 0xA9F0..=0xA9F9
797
- // Cham digits
798
- | 0xAA50..=0xAA59
799
- // Meetei Mayek digits
800
- | 0xABF0..=0xABF9
801
- // Fullwidth digits
802
- | 0xFF10..=0xFF19
803
- // Osmanya digits
804
- | 0x104A0..=0x104A9
805
- // Hanifi Rohingya digits
806
- | 0x10D30..=0x10D39
807
- // Brahmi digits
808
- | 0x11066..=0x1106F
809
- // Sora Sompeng digits
810
- | 0x110F0..=0x110F9
811
- // Chakma digits
812
- | 0x11136..=0x1113F
813
- // Sharada digits
814
- | 0x111D0..=0x111D9
815
- // Khudawadi digits
816
- | 0x112F0..=0x112F9
817
- // Newa digits
818
- | 0x11450..=0x11459
819
- // Tirhuta digits
820
- | 0x114D0..=0x114D9
821
- // Modi digits
822
- | 0x11650..=0x11659
823
- // Takri digits
824
- | 0x116C0..=0x116C9
825
- // Ahom digits
826
- | 0x11730..=0x11739
827
- // Warang Citi digits
828
- | 0x118E0..=0x118E9
829
- // Dives Akuru digits
830
- | 0x11950..=0x11959
831
- // Bhaiksuki digits
832
- | 0x11C50..=0x11C59
833
- // Masaram Gondi digits
834
- | 0x11D50..=0x11D59
835
- // Gunjala Gondi digits
836
- | 0x11DA0..=0x11DA9
837
- // Adlam digits
838
- | 0x1E950..=0x1E959
839
- // Segmented digits
840
- | 0x1FBF0..=0x1FBF9
841
- )
842
- }
843
-
844
- /// Checks if a character is a Unicode digit (isdigit).
845
- ///
846
- /// This includes decimal digits (Nd) plus characters with Numeric_Type=Digit
847
- /// such as superscripts, subscripts, and circled digits.
848
- fn is_unicode_digit(c: char) -> bool {
849
- // First check if it's a decimal digit
850
- if is_unicode_decimal(c) {
851
- return true;
852
- }
853
-
854
- let cp = c as u32;
855
- matches!(
856
- cp,
857
- // Superscripts (², ³)
858
- 0x00B2..=0x00B3
859
- // Superscript 1
860
- | 0x00B9
861
- // Superscript digits 0, 4-9
862
- | 0x2070
863
- | 0x2074..=0x2079
864
- // Subscript digits 0-9
865
- | 0x2080..=0x2089
866
- // Circled digits 1-9
867
- | 0x2460..=0x2468
868
- // Circled digit 0
869
- | 0x24EA
870
- // Circled digits 10-20
871
- | 0x2469..=0x2473
872
- // Parenthesized digits 1-9
873
- | 0x2474..=0x247C
874
- // Period digits 1-9
875
- | 0x2488..=0x2490
876
- // Double circled digits 1-10
877
- | 0x24F5..=0x24FE
878
- // Dingbat circled sans-serif digits 1-10
879
- | 0x2780..=0x2789
880
- // Dingbat negative circled digits 1-10
881
- | 0x278A..=0x2793
882
- // Dingbat circled sans-serif digits 1-10
883
- | 0x24FF
884
- // Fullwidth digit zero (already in decimal, but include for completeness)
885
- // | 0xFF10..=0xFF19 // Already covered by is_unicode_decimal
886
- )
887
- }
888
-
889
- // =============================================================================
890
- // Search methods
891
- // =============================================================================
892
-
893
- /// Implements Python's `str.find(sub, start?, end?)` method.
894
- ///
895
- /// Returns the lowest index in the string where substring sub is found within
896
- /// the slice s[start:end]. Returns -1 if sub is not found.
897
- fn str_find(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
898
- let (sub, start, end) = parse_search_args("str.find", s, args, vm)?;
899
- let slice = slice_string(s, start, end);
900
- let result = match slice.find(&sub) {
901
- Some(pos) => {
902
- // Convert byte offset to char offset, then add start offset
903
- let char_pos = slice[..pos].chars().count();
904
- i64::try_from(start + char_pos).unwrap_or(i64::MAX)
905
- }
906
- None => -1,
907
- };
908
- Ok(Value::Int(result))
909
- }
910
-
911
- /// Implements Python's `str.rfind(sub, start?, end?)` method.
912
- ///
913
- /// Returns the highest index in the string where substring sub is found within
914
- /// the slice s[start:end]. Returns -1 if sub is not found.
915
- fn str_rfind(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
916
- let (sub, start, end) = parse_search_args("str.rfind", s, args, vm)?;
917
- let slice = slice_string(s, start, end);
918
- let result = match slice.rfind(&sub) {
919
- Some(pos) => {
920
- // Convert byte offset to char offset, then add start offset
921
- let char_pos = slice[..pos].chars().count();
922
- i64::try_from(start + char_pos).unwrap_or(i64::MAX)
923
- }
924
- None => -1,
925
- };
926
- Ok(Value::Int(result))
927
- }
928
-
929
- /// Implements Python's `str.index(sub, start?, end?)` method.
930
- ///
931
- /// Like find(), but raises ValueError when the substring is not found.
932
- fn str_index(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
933
- let (sub, start, end) = parse_search_args("str.index", s, args, vm)?;
934
- let slice = slice_string(s, start, end);
935
- match slice.find(&sub) {
936
- Some(pos) => {
937
- let char_pos = slice[..pos].chars().count();
938
- let result = i64::try_from(start + char_pos).unwrap_or(i64::MAX);
939
- Ok(Value::Int(result))
940
- }
941
- None => Err(ExcType::value_error_substring_not_found()),
942
- }
943
- }
944
-
945
- /// Implements Python's `str.rindex(sub, start?, end?)` method.
946
- ///
947
- /// Like rfind(), but raises ValueError when the substring is not found.
948
- fn str_rindex(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
949
- let (sub, start, end) = parse_search_args("str.rindex", s, args, vm)?;
950
- let slice = slice_string(s, start, end);
951
- match slice.rfind(&sub) {
952
- Some(pos) => {
953
- let char_pos = slice[..pos].chars().count();
954
- let result = i64::try_from(start + char_pos).unwrap_or(i64::MAX);
955
- Ok(Value::Int(result))
956
- }
957
- None => Err(ExcType::value_error_substring_not_found()),
958
- }
959
- }
960
-
961
- /// Implements Python's `str.count(sub, start?, end?)` method.
962
- ///
963
- /// Returns the number of non-overlapping occurrences of substring sub in
964
- /// the string s[start:end].
965
- fn str_count(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
966
- let (sub, start, end) = parse_search_args("str.count", s, args, vm)?;
967
- let slice = slice_string(s, start, end);
968
- let count = if sub.is_empty() {
969
- // Empty string matches between every character, plus start and end
970
- slice.chars().count() + 1
971
- } else {
972
- slice.matches(&sub).count()
973
- };
974
- let result = i64::try_from(count).unwrap_or(i64::MAX);
975
- Ok(Value::Int(result))
976
- }
977
-
978
- /// Implements Python's `str.startswith(prefix, start?, end?)` method.
979
- ///
980
- /// Returns True if the string starts with the prefix, otherwise returns False.
981
- /// The prefix argument can be a string or a tuple of strings.
982
- fn str_startswith(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
983
- let (prefixes, start, end) = parse_prefix_suffix_args("str.startswith", s, args, vm)?;
984
- let slice = slice_string(s, start, end);
985
- let result = prefixes.iter().any(|prefix| slice.starts_with(prefix));
986
- Ok(Value::Bool(result))
987
- }
988
-
989
- /// Implements Python's `str.endswith(suffix, start?, end?)` method.
990
- ///
991
- /// Returns True if the string ends with the suffix, otherwise returns False.
992
- /// The suffix argument can be a string or a tuple of strings.
993
- fn str_endswith(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
994
- let (suffixes, start, end) = parse_prefix_suffix_args("str.endswith", s, args, vm)?;
995
- let slice = slice_string(s, start, end);
996
- let result = suffixes.iter().any(|suffix| slice.ends_with(suffix));
997
- Ok(Value::Bool(result))
998
- }
999
-
1000
- /// Parses arguments for search methods (find, rfind, index, rindex, count, startswith, endswith).
1001
- ///
1002
- /// Returns (substring, start, end) where start and end are character indices.
1003
- fn parse_search_args(
1004
- method: &str,
1005
- s: &str,
1006
- args: ArgValues,
1007
- vm: &mut VM<'_, '_, impl ResourceTracker>,
1008
- ) -> RunResult<(String, usize, usize)> {
1009
- let pos = args.into_pos_only(method, vm.heap)?;
1010
- defer_drop!(pos, vm);
1011
-
1012
- let str_len = s.chars().count();
1013
- match pos.as_slice() {
1014
- [sub_value] => {
1015
- let sub = extract_string_arg(sub_value, vm)?;
1016
- Ok((sub, 0, str_len))
1017
- }
1018
- [sub_value, start_value] => {
1019
- let sub = extract_string_arg(sub_value, vm)?;
1020
- let start = optional_index(start_value, 0, str_len, vm.heap)?;
1021
- Ok((sub, start, str_len))
1022
- }
1023
- [sub_value, start_value, end_value] => {
1024
- let sub = extract_string_arg(sub_value, vm)?;
1025
- let start = optional_index(start_value, 0, str_len, vm.heap)?;
1026
- let end = optional_index(end_value, str_len, str_len, vm.heap)?;
1027
- Ok((sub, start, end))
1028
- }
1029
- [] => Err(ExcType::type_error_at_least(method, 1, 0)),
1030
- _ => Err(ExcType::type_error_at_most(method, 3, pos.len())),
1031
- }
1032
- }
1033
-
1034
- /// Parses arguments for startswith/endswith methods.
1035
- ///
1036
- /// Returns (prefixes/suffixes as Vec, start, end) where start and end are character indices.
1037
- /// The first argument can be either a string or a tuple of strings.
1038
- fn parse_prefix_suffix_args(
1039
- method: &str,
1040
- s: &str,
1041
- args: ArgValues,
1042
- vm: &mut VM<'_, '_, impl ResourceTracker>,
1043
- ) -> RunResult<(Vec<String>, usize, usize)> {
1044
- let pos = args.into_pos_only(method, vm.heap)?;
1045
- defer_drop!(pos, vm);
1046
-
1047
- let str_len = s.chars().count();
1048
- match pos.as_slice() {
1049
- [prefix_value] => {
1050
- let prefixes = extract_str_or_tuple_of_str(prefix_value, vm)?;
1051
- Ok((prefixes, 0, str_len))
1052
- }
1053
- [prefix_value, start_value] => {
1054
- let prefixes = extract_str_or_tuple_of_str(prefix_value, vm)?;
1055
- let start = optional_index(start_value, 0, str_len, vm.heap)?;
1056
- Ok((prefixes, start, str_len))
1057
- }
1058
- [prefix_value, start_value, end_value] => {
1059
- let prefixes = extract_str_or_tuple_of_str(prefix_value, vm)?;
1060
- let start = optional_index(start_value, 0, str_len, vm.heap)?;
1061
- let end = optional_index(end_value, str_len, str_len, vm.heap)?;
1062
- Ok((prefixes, start, end))
1063
- }
1064
- [] => Err(ExcType::type_error_at_least(method, 1, 0)),
1065
- _ => Err(ExcType::type_error_at_most(method, 3, pos.len())),
1066
- }
1067
- }
1068
-
1069
- /// Extracts a string or tuple of strings from a Value.
1070
- ///
1071
- /// Returns a Vec of strings - a single-element Vec if given a string,
1072
- /// or multiple elements if given a tuple of strings.
1073
- fn extract_str_or_tuple_of_str(value: &Value, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Vec<String>> {
1074
- match value {
1075
- Value::InternString(id) => Ok(vec![vm.interns.get_str(*id).to_owned()]),
1076
- Value::Ref(heap_id) => match vm.heap.get(*heap_id) {
1077
- HeapData::Str(s) => Ok(vec![s.as_str().to_owned()]),
1078
- HeapData::Tuple(tuple) => {
1079
- // Inline string extraction to avoid borrow conflict — vm.heap is
1080
- // already borrowed immutably to access the tuple's items.
1081
- let items = tuple.as_slice();
1082
- let mut strings = Vec::with_capacity(items.len());
1083
- for item in items {
1084
- match item {
1085
- Value::InternString(id) => {
1086
- strings.push(vm.interns.get_str(*id).to_owned());
1087
- }
1088
- Value::Ref(hid) => {
1089
- if let HeapData::Str(s) = vm.heap.get(*hid) {
1090
- strings.push(s.as_str().to_owned());
1091
- } else {
1092
- return Err(ExcType::type_error("expected str or tuple of str"));
1093
- }
1094
- }
1095
- _ => return Err(ExcType::type_error("expected str or tuple of str")),
1096
- }
1097
- }
1098
- Ok(strings)
1099
- }
1100
- _ => Err(ExcType::type_error("expected str or tuple of str")),
1101
- },
1102
- _ => Err(ExcType::type_error("expected str or tuple of str")),
1103
- }
1104
- }
1105
-
1106
- /// Extracts a string from a Value, returning an error if not a string.
1107
- fn extract_string_arg(value: &Value, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<String> {
1108
- match value {
1109
- Value::InternString(id) => Ok(vm.interns.get_str(*id).to_owned()),
1110
- Value::Ref(heap_id) => {
1111
- if let HeapData::Str(s) = vm.heap.get(*heap_id) {
1112
- Ok(s.as_str().to_owned())
1113
- } else {
1114
- Err(ExcType::type_error("expected str"))
1115
- }
1116
- }
1117
- _ => Err(ExcType::type_error("expected str")),
1118
- }
1119
- }
1120
-
1121
- /// Extracts an integer from a Value, returning an error if not an integer.
1122
- fn extract_int_arg(value: &Value, heap: &Heap<impl ResourceTracker>) -> RunResult<i64> {
1123
- match value {
1124
- Value::Int(i) => Ok(*i),
1125
- Value::Ref(heap_id) => {
1126
- if let HeapData::LongInt(li) = heap.get(*heap_id) {
1127
- // Try to convert to i64
1128
- li.to_i64().ok_or_else(|| ExcType::type_error("integer too large"))
1129
- } else {
1130
- Err(ExcType::type_error("expected int"))
1131
- }
1132
- }
1133
- _ => Err(ExcType::type_error("expected int")),
1134
- }
1135
- }
1136
-
1137
- /// Normalizes a Python-style index to a valid index in range [0, len].
1138
- fn normalize_index(index: i64, len: usize) -> usize {
1139
- if index < 0 {
1140
- // Safe cast: we've checked index is negative, so -index is positive
1141
- // For very large negative numbers that don't fit in usize, saturate to usize::MAX
1142
- let abs_index = usize::try_from(-index).unwrap_or(usize::MAX);
1143
- len.saturating_sub(abs_index)
1144
- } else {
1145
- // Safe cast: we've checked index is non-negative
1146
- // For values > usize::MAX, saturate to len
1147
- usize::try_from(index).unwrap_or(len).min(len)
1148
- }
1149
- }
1150
-
1151
- /// Extracts an optional index from a `Value`, treating `None` as `default`.
1152
- ///
1153
- /// Used by argument parsers where `None` means "use the default index" and
1154
- /// any other value is interpreted as an integer and normalized against `str_len`.
1155
- fn optional_index(
1156
- value: &Value,
1157
- default: usize,
1158
- str_len: usize,
1159
- heap: &Heap<impl ResourceTracker>,
1160
- ) -> RunResult<usize> {
1161
- if matches!(value, Value::None) {
1162
- Ok(default)
1163
- } else {
1164
- Ok(normalize_index(extract_int_arg(value, heap)?, str_len))
1165
- }
1166
- }
1167
-
1168
- /// Returns a substring of s from character index start to end.
1169
- fn slice_string(s: &str, start: usize, end: usize) -> &str {
1170
- if start >= end {
1171
- return "";
1172
- }
1173
-
1174
- let mut start_byte = s.len();
1175
- let mut end_byte = s.len();
1176
-
1177
- for (char_idx, (byte_idx, _)) in s.char_indices().enumerate() {
1178
- if char_idx == start {
1179
- start_byte = byte_idx;
1180
- }
1181
- if char_idx == end {
1182
- end_byte = byte_idx;
1183
- break;
1184
- }
1185
- }
1186
-
1187
- &s[start_byte..end_byte]
1188
- }
1189
-
1190
- // =============================================================================
1191
- // Strip/trim methods
1192
- // =============================================================================
1193
-
1194
- /// Implements Python's `str.strip(chars?)` method.
1195
- ///
1196
- /// Returns a copy of the string with leading and trailing characters removed.
1197
- /// If chars is not specified, whitespace characters are removed.
1198
- fn str_strip(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1199
- let chars = parse_strip_arg("str.strip", args, vm)?;
1200
- let result = match &chars {
1201
- Some(c) => s.trim_matches(|ch| c.contains(ch)).to_owned(),
1202
- None => s.trim().to_owned(),
1203
- };
1204
- allocate_string(result, vm.heap)
1205
- }
1206
-
1207
- /// Implements Python's `str.lstrip(chars?)` method.
1208
- ///
1209
- /// Returns a copy of the string with leading characters removed.
1210
- fn str_lstrip(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1211
- let chars = parse_strip_arg("str.lstrip", args, vm)?;
1212
- let result = match &chars {
1213
- Some(c) => s.trim_start_matches(|ch| c.contains(ch)).to_owned(),
1214
- None => s.trim_start().to_owned(),
1215
- };
1216
- allocate_string(result, vm.heap)
1217
- }
1218
-
1219
- /// Implements Python's `str.rstrip(chars?)` method.
1220
- ///
1221
- /// Returns a copy of the string with trailing characters removed.
1222
- fn str_rstrip(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1223
- let chars = parse_strip_arg("str.rstrip", args, vm)?;
1224
- let result = match &chars {
1225
- Some(c) => s.trim_end_matches(|ch| c.contains(ch)).to_owned(),
1226
- None => s.trim_end().to_owned(),
1227
- };
1228
- allocate_string(result, vm.heap)
1229
- }
1230
-
1231
- /// Parses the optional chars argument for strip methods.
1232
- ///
1233
- /// Accepts None as a value meaning "use default whitespace stripping".
1234
- fn parse_strip_arg(
1235
- method: &str,
1236
- args: ArgValues,
1237
- vm: &mut VM<'_, '_, impl ResourceTracker>,
1238
- ) -> RunResult<Option<String>> {
1239
- let value = args.get_zero_one_arg(method, vm.heap)?;
1240
- match value {
1241
- None => Ok(None),
1242
- Some(Value::None) => Ok(None), // Explicit None means default whitespace
1243
- Some(v) => {
1244
- defer_drop!(v, vm);
1245
- let result = extract_string_arg(v, vm)?;
1246
- Ok(Some(result))
1247
- }
1248
- }
1249
- }
1250
-
1251
- /// Implements Python's `str.removeprefix(prefix)` method.
1252
- ///
1253
- /// If the string starts with the prefix string, return string[len(prefix):].
1254
- /// Otherwise, return a copy of the original string.
1255
- fn str_removeprefix(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1256
- let prefix_value = args.get_one_arg("str.removeprefix", vm.heap)?;
1257
- defer_drop!(prefix_value, vm);
1258
- let prefix = extract_string_arg(prefix_value, vm)?;
1259
-
1260
- let result = s.strip_prefix(&prefix).unwrap_or(s).to_owned();
1261
- allocate_string(result, vm.heap)
1262
- }
1263
-
1264
- /// Implements Python's `str.removesuffix(suffix)` method.
1265
- ///
1266
- /// If the string ends with the suffix string, return string[:-len(suffix)].
1267
- /// Otherwise, return a copy of the original string.
1268
- fn str_removesuffix(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1269
- let suffix_value = args.get_one_arg("str.removesuffix", vm.heap)?;
1270
- defer_drop!(suffix_value, vm);
1271
- let suffix = extract_string_arg(suffix_value, vm)?;
1272
-
1273
- let result = s.strip_suffix(&suffix).unwrap_or(s).to_owned();
1274
- allocate_string(result, vm.heap)
1275
- }
1276
-
1277
- // =============================================================================
1278
- // Split methods
1279
- // =============================================================================
1280
-
1281
- /// Implements Python's `str.split(sep?, maxsplit?)` method.
1282
- ///
1283
- /// Returns a list of the words in the string, using sep as the delimiter string.
1284
- fn str_split(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1285
- let (sep, maxsplit) = parse_split_args("str.split", args, vm)?;
1286
-
1287
- let parts: Vec<&str> = match &sep {
1288
- Some(sep) => {
1289
- // Empty separator raises ValueError
1290
- if sep.is_empty() {
1291
- return Err(ExcType::value_error_empty_separator());
1292
- }
1293
- if maxsplit < 0 {
1294
- s.split(sep.as_str()).collect()
1295
- } else {
1296
- // Safe cast: we've checked maxsplit >= 0
1297
- let max = usize::try_from(maxsplit).unwrap_or(usize::MAX);
1298
- s.splitn(max.saturating_add(1), sep.as_str()).collect()
1299
- }
1300
- }
1301
- None => {
1302
- // Split on whitespace, filtering empty strings
1303
- if maxsplit < 0 {
1304
- s.split_whitespace().collect()
1305
- } else {
1306
- // Safe cast: we've checked maxsplit >= 0
1307
- let max = usize::try_from(maxsplit).unwrap_or(usize::MAX);
1308
- split_whitespace_n(s, max)
1309
- }
1310
- }
1311
- };
1312
-
1313
- // Convert to list of strings (using interned empty string when applicable)
1314
- let mut list_items = Vec::with_capacity(parts.len());
1315
- for part in parts {
1316
- vm.heap.check_time()?;
1317
- list_items.push(allocate_string(part.to_owned(), vm.heap)?);
1318
- }
1319
-
1320
- let list = crate::types::List::new(list_items);
1321
- let heap_id = vm.heap.allocate(HeapData::List(list))?;
1322
- Ok(Value::Ref(heap_id))
1323
- }
1324
-
1325
- /// Implements Python's `str.rsplit(sep?, maxsplit?)` method.
1326
- ///
1327
- /// Returns a list of the words in the string, using sep as the delimiter string,
1328
- /// splitting from the right.
1329
- fn str_rsplit(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1330
- let (sep, maxsplit) = parse_split_args("str.rsplit", args, vm)?;
1331
-
1332
- let parts: Vec<&str> = match &sep {
1333
- Some(sep) => {
1334
- // Empty separator raises ValueError
1335
- if sep.is_empty() {
1336
- return Err(ExcType::value_error_empty_separator());
1337
- }
1338
- if maxsplit < 0 {
1339
- s.rsplit(sep.as_str()).collect::<Vec<_>>().into_iter().rev().collect()
1340
- } else {
1341
- // Safe cast: we've checked maxsplit >= 0
1342
- let max = usize::try_from(maxsplit).unwrap_or(usize::MAX);
1343
- let mut parts: Vec<_> = s.rsplitn(max.saturating_add(1), sep.as_str()).collect();
1344
- parts.reverse();
1345
- parts
1346
- }
1347
- }
1348
- None => {
1349
- // Split on whitespace from right
1350
- if maxsplit < 0 {
1351
- s.split_whitespace().collect()
1352
- } else {
1353
- // Safe cast: we've checked maxsplit >= 0
1354
- let max = usize::try_from(maxsplit).unwrap_or(usize::MAX);
1355
- rsplit_whitespace_n(s, max)
1356
- }
1357
- }
1358
- };
1359
-
1360
- // Convert to list of strings (using interned empty string when applicable)
1361
- let mut list_items = Vec::with_capacity(parts.len());
1362
- for part in parts {
1363
- vm.heap.check_time()?;
1364
- list_items.push(allocate_string(part.to_owned(), vm.heap)?);
1365
- }
1366
-
1367
- let list = crate::types::List::new(list_items);
1368
- let heap_id = vm.heap.allocate(HeapData::List(list))?;
1369
- Ok(Value::Ref(heap_id))
1370
- }
1371
-
1372
- /// Parses arguments for split methods.
1373
- ///
1374
- /// Supports both positional and keyword arguments for sep and maxsplit.
1375
- fn parse_split_args(
1376
- method: &str,
1377
- args: ArgValues,
1378
- vm: &mut VM<'_, '_, impl ResourceTracker>,
1379
- ) -> RunResult<(Option<String>, i64)> {
1380
- let (pos, kwargs) = args.into_parts();
1381
- let kwargs_iter = kwargs.into_iter();
1382
- defer_drop_mut!(kwargs_iter, vm);
1383
-
1384
- let mut pos_iter = pos;
1385
- let sep_value = pos_iter.next();
1386
- defer_drop_mut!(sep_value, vm);
1387
- let maxsplit_value = pos_iter.next();
1388
- defer_drop_mut!(maxsplit_value, vm);
1389
-
1390
- // Check no extra positional arguments
1391
- if pos_iter.len() != 0 {
1392
- return Err(ExcType::type_error_at_most(method, 2, 3));
1393
- }
1394
-
1395
- // Extract positional sep (default None)
1396
- let mut has_pos_sep = sep_value.is_some();
1397
- let mut sep = if let Some(v) = sep_value.as_ref() {
1398
- if matches!(v, Value::None) {
1399
- None
1400
- } else {
1401
- Some(extract_string_arg(v, vm)?)
1402
- }
1403
- } else {
1404
- None
1405
- };
1406
-
1407
- // Extract positional maxsplit (default -1)
1408
- let mut has_pos_maxsplit = maxsplit_value.is_some();
1409
- let mut maxsplit = if let Some(v) = maxsplit_value.as_ref() {
1410
- extract_int_arg(v, vm.heap)?
1411
- } else {
1412
- -1
1413
- };
1414
-
1415
- // Process kwargs
1416
- for (key, value) in kwargs_iter {
1417
- defer_drop!(key, vm);
1418
- defer_drop!(value, vm);
1419
-
1420
- let Some(keyword_name) = key.as_either_str(vm.heap) else {
1421
- return Err(ExcType::type_error("keywords must be strings"));
1422
- };
1423
-
1424
- let key_str = keyword_name.as_str(vm.interns);
1425
- match key_str {
1426
- "sep" => {
1427
- if has_pos_sep {
1428
- return Err(ExcType::type_error(format!(
1429
- "{method}() got multiple values for argument 'sep'"
1430
- )));
1431
- }
1432
- if matches!(value, Value::None) {
1433
- sep = None;
1434
- } else {
1435
- sep = Some(extract_string_arg(value, vm)?);
1436
- }
1437
- has_pos_sep = true;
1438
- }
1439
- "maxsplit" => {
1440
- if has_pos_maxsplit {
1441
- return Err(ExcType::type_error(format!(
1442
- "{method}() got multiple values for argument 'maxsplit'"
1443
- )));
1444
- }
1445
- maxsplit = extract_int_arg(value, vm.heap)?;
1446
- has_pos_maxsplit = true;
1447
- }
1448
- _ => {
1449
- return Err(ExcType::type_error(format!(
1450
- "'{key_str}' is an invalid keyword argument for {method}()"
1451
- )));
1452
- }
1453
- }
1454
- }
1455
-
1456
- Ok((sep, maxsplit))
1457
- }
1458
-
1459
- /// Split string on whitespace, returning at most `maxsplit + 1` parts.
1460
- fn split_whitespace_n(s: &str, maxsplit: usize) -> Vec<&str> {
1461
- let mut parts = Vec::new();
1462
- let mut remaining = s.trim_start();
1463
- let mut count = 0;
1464
-
1465
- while !remaining.is_empty() && count < maxsplit {
1466
- if let Some(end) = remaining.find(|c: char| c.is_whitespace()) {
1467
- parts.push(&remaining[..end]);
1468
- remaining = remaining[end..].trim_start();
1469
- count += 1;
1470
- } else {
1471
- break;
1472
- }
1473
- }
1474
-
1475
- if !remaining.is_empty() {
1476
- parts.push(remaining);
1477
- }
1478
-
1479
- parts
1480
- }
1481
-
1482
- /// Split string on whitespace from the right, returning at most `maxsplit + 1` parts.
1483
- fn rsplit_whitespace_n(s: &str, maxsplit: usize) -> Vec<&str> {
1484
- let mut parts = Vec::new();
1485
- let mut remaining = s.trim_end();
1486
- let mut count = 0;
1487
-
1488
- while !remaining.is_empty() && count < maxsplit {
1489
- if let Some(start) = remaining.rfind(|c: char| c.is_whitespace()) {
1490
- parts.push(&remaining[start + 1..]);
1491
- remaining = remaining[..start].trim_end();
1492
- count += 1;
1493
- } else {
1494
- break;
1495
- }
1496
- }
1497
-
1498
- if !remaining.is_empty() {
1499
- parts.push(remaining);
1500
- }
1501
-
1502
- parts.reverse();
1503
- parts
1504
- }
1505
-
1506
- /// Implements Python's `str.splitlines(keepends?)` method.
1507
- ///
1508
- /// Returns a list of the lines in the string, breaking at line boundaries.
1509
- /// Accepts keepends as either positional or keyword argument.
1510
- fn str_splitlines(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1511
- let keepends = parse_splitlines_args(args, vm)?;
1512
-
1513
- let mut lines = Vec::new();
1514
- let mut start = 0;
1515
- let bytes = s.as_bytes();
1516
- let len = bytes.len();
1517
-
1518
- while start < len {
1519
- vm.heap.check_time()?;
1520
-
1521
- // Find the next line ending
1522
- let mut end = start;
1523
- let mut line_end = start;
1524
-
1525
- while end < len {
1526
- match bytes[end] {
1527
- b'\n' => {
1528
- line_end = end;
1529
- end += 1;
1530
- break;
1531
- }
1532
- b'\r' => {
1533
- line_end = end;
1534
- end += 1;
1535
- // Check for \r\n
1536
- if end < len && bytes[end] == b'\n' {
1537
- end += 1;
1538
- }
1539
- break;
1540
- }
1541
- _ => {
1542
- end += 1;
1543
- line_end = end;
1544
- }
1545
- }
1546
- }
1547
-
1548
- let line = if keepends { &s[start..end] } else { &s[start..line_end] };
1549
-
1550
- lines.push(allocate_string(line.to_owned(), vm.heap)?);
1551
-
1552
- start = end;
1553
- }
1554
-
1555
- let list = crate::types::List::new(lines);
1556
- let heap_id = vm.heap.allocate(HeapData::List(list))?;
1557
- Ok(Value::Ref(heap_id))
1558
- }
1559
-
1560
- /// Parses arguments for splitlines method.
1561
- ///
1562
- /// Supports both positional and keyword arguments for keepends.
1563
- fn parse_splitlines_args(args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<bool> {
1564
- let (pos, kwargs) = args.into_parts();
1565
- let kwargs_iter = kwargs.into_iter();
1566
- defer_drop_mut!(kwargs_iter, vm);
1567
-
1568
- let mut pos_iter = pos;
1569
- let keepends_value = pos_iter.next();
1570
- defer_drop_mut!(keepends_value, vm);
1571
-
1572
- // Check no extra positional arguments
1573
- if pos_iter.len() != 0 {
1574
- return Err(ExcType::type_error_at_most("str.splitlines", 1, 2));
1575
- }
1576
-
1577
- // Extract positional keepends (default false)
1578
- let mut has_pos_keepends = keepends_value.is_some();
1579
- let mut keepends = if let Some(v) = keepends_value.as_ref() {
1580
- value_is_truthy(v)
1581
- } else {
1582
- false
1583
- };
1584
-
1585
- // Process kwargs
1586
- for (key, value) in kwargs_iter {
1587
- defer_drop!(key, vm);
1588
- defer_drop!(value, vm);
1589
-
1590
- let Some(keyword_name) = key.as_either_str(vm.heap) else {
1591
- return Err(ExcType::type_error("keywords must be strings"));
1592
- };
1593
-
1594
- let key_str = keyword_name.as_str(vm.interns);
1595
- if key_str == "keepends" {
1596
- if has_pos_keepends {
1597
- return Err(ExcType::type_error(
1598
- "str.splitlines() got multiple values for argument 'keepends'",
1599
- ));
1600
- }
1601
- keepends = value_is_truthy(value);
1602
- has_pos_keepends = true;
1603
- } else {
1604
- return Err(ExcType::type_error(format!(
1605
- "'{key_str}' is an invalid keyword argument for str.splitlines()"
1606
- )));
1607
- }
1608
- }
1609
-
1610
- Ok(keepends)
1611
- }
1612
-
1613
- /// Checks if a value is truthy for bool conversion.
1614
- fn value_is_truthy(v: &Value) -> bool {
1615
- match v {
1616
- Value::Bool(b) => *b,
1617
- Value::Int(i) => *i != 0,
1618
- Value::None => false,
1619
- _ => true, // Most other values are truthy
1620
- }
1621
- }
1622
-
1623
- /// Implements Python's `str.partition(sep)` method.
1624
- ///
1625
- /// Splits the string at the first occurrence of sep, and returns a 3-tuple
1626
- /// containing the part before the separator, the separator itself, and the part after.
1627
- fn str_partition(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1628
- let sep_value = args.get_one_arg("str.partition", vm.heap)?;
1629
- defer_drop!(sep_value, vm);
1630
- let sep = extract_string_arg(sep_value, vm)?;
1631
-
1632
- if sep.is_empty() {
1633
- return Err(ExcType::value_error_empty_separator());
1634
- }
1635
-
1636
- let (before, sep_found, after) = match s.find(&sep) {
1637
- Some(pos) => (&s[..pos], &sep[..], &s[pos + sep.len()..]),
1638
- None => (s, "", ""),
1639
- };
1640
-
1641
- let before_val = allocate_string(before.to_owned(), vm.heap)?;
1642
- let sep_val = allocate_string(sep_found.to_owned(), vm.heap)?;
1643
- let after_val = allocate_string(after.to_owned(), vm.heap)?;
1644
-
1645
- Ok(crate::types::allocate_tuple(
1646
- smallvec![before_val, sep_val, after_val],
1647
- vm.heap,
1648
- )?)
1649
- }
1650
-
1651
- /// Implements Python's `str.rpartition(sep)` method.
1652
- ///
1653
- /// Splits the string at the last occurrence of sep, and returns a 3-tuple
1654
- /// containing the part before the separator, the separator itself, and the part after.
1655
- fn str_rpartition(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1656
- let sep_value = args.get_one_arg("str.rpartition", vm.heap)?;
1657
- defer_drop!(sep_value, vm);
1658
- let sep = extract_string_arg(sep_value, vm)?;
1659
-
1660
- if sep.is_empty() {
1661
- return Err(ExcType::value_error_empty_separator());
1662
- }
1663
-
1664
- let (before, sep_found, after) = match s.rfind(&sep) {
1665
- Some(pos) => (&s[..pos], &sep[..], &s[pos + sep.len()..]),
1666
- None => ("", "", s),
1667
- };
1668
-
1669
- let before_val = allocate_string(before.to_owned(), vm.heap)?;
1670
- let sep_val = allocate_string(sep_found.to_owned(), vm.heap)?;
1671
- let after_val = allocate_string(after.to_owned(), vm.heap)?;
1672
-
1673
- Ok(crate::types::allocate_tuple(
1674
- smallvec![before_val, sep_val, after_val],
1675
- vm.heap,
1676
- )?)
1677
- }
1678
-
1679
- // =============================================================================
1680
- // Replace/modify methods
1681
- // =============================================================================
1682
-
1683
- /// Implements Python's `str.replace(old, new, count?)` method.
1684
- ///
1685
- /// Returns a copy with all occurrences of substring old replaced by new.
1686
- /// If count is given, only the first count occurrences are replaced.
1687
- fn str_replace(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1688
- let (old, new, count) = parse_replace_args("str.replace", args, vm)?;
1689
-
1690
- check_replace_size(s.len(), old.len(), new.len(), count, vm.heap.tracker())?;
1691
-
1692
- let result = if count < 0 {
1693
- s.replace(&old, &new)
1694
- } else {
1695
- // Safe cast: we've checked count >= 0
1696
- let n = usize::try_from(count).unwrap_or(usize::MAX);
1697
- s.replacen(&old, &new, n)
1698
- };
1699
-
1700
- allocate_string(result, vm.heap)
1701
- }
1702
-
1703
- /// Parses arguments for the replace method.
1704
- ///
1705
- /// Supports both positional and keyword arguments for count (Python 3.13+).
1706
- fn parse_replace_args(
1707
- method: &str,
1708
- args: ArgValues,
1709
- vm: &mut VM<'_, '_, impl ResourceTracker>,
1710
- ) -> RunResult<(String, String, i64)> {
1711
- let (pos, kwargs) = args.into_parts();
1712
- let kwargs_iter = kwargs.into_iter();
1713
- defer_drop_mut!(kwargs_iter, vm);
1714
-
1715
- let mut pos_iter = pos;
1716
- let Some(old_value) = pos_iter.next() else {
1717
- return Err(ExcType::type_error_at_least(method, 2, 0));
1718
- };
1719
- defer_drop!(old_value, vm);
1720
-
1721
- let Some(new_value) = pos_iter.next() else {
1722
- return Err(ExcType::type_error_at_least(method, 2, 1));
1723
- };
1724
- defer_drop!(new_value, vm);
1725
-
1726
- let count_value = pos_iter.next();
1727
- defer_drop_mut!(count_value, vm);
1728
-
1729
- // Check no extra positional arguments
1730
- if pos_iter.len() != 0 {
1731
- return Err(ExcType::type_error_at_most(method, 3, 4));
1732
- }
1733
-
1734
- let old = extract_string_arg(old_value, vm)?;
1735
- let new = extract_string_arg(new_value, vm)?;
1736
-
1737
- let mut has_pos_count = count_value.is_some();
1738
- let mut count = if let Some(v) = count_value.as_ref() {
1739
- extract_int_arg(v, vm.heap)?
1740
- } else {
1741
- -1
1742
- };
1743
-
1744
- // Process kwargs (Python 3.13+ allows count as keyword)
1745
- for (key, value) in kwargs_iter {
1746
- defer_drop!(key, vm);
1747
- defer_drop!(value, vm);
1748
-
1749
- let Some(keyword_name) = key.as_either_str(vm.heap) else {
1750
- return Err(ExcType::type_error("keywords must be strings"));
1751
- };
1752
-
1753
- let key_str = keyword_name.as_str(vm.interns);
1754
- if key_str == "count" {
1755
- if has_pos_count {
1756
- return Err(ExcType::type_error(format!(
1757
- "{method}() got multiple values for argument 'count'"
1758
- )));
1759
- }
1760
- count = extract_int_arg(value, vm.heap)?;
1761
- has_pos_count = true;
1762
- } else {
1763
- return Err(ExcType::type_error(format!(
1764
- "'{key_str}' is an invalid keyword argument for {method}()"
1765
- )));
1766
- }
1767
- }
1768
-
1769
- Ok((old, new, count))
1770
- }
1771
-
1772
- /// Implements Python's `str.center(width, fillchar?)` method.
1773
- ///
1774
- /// Returns centered in a string of length width. Padding is done using the
1775
- /// specified fill character (default is a space).
1776
- fn str_center(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1777
- let (width, fillchar) = parse_justify_args("str.center", args, vm)?;
1778
- let len = s.chars().count();
1779
-
1780
- let result = if width <= len {
1781
- s.to_owned()
1782
- } else {
1783
- check_repeat_size(width, fillchar.len_utf8(), vm.heap.tracker())?;
1784
- let total_pad = width - len;
1785
- let left_pad = total_pad / 2;
1786
- let right_pad = total_pad - left_pad;
1787
- let mut result = String::with_capacity(width);
1788
- for _ in 0..left_pad {
1789
- result.push(fillchar);
1790
- }
1791
- result.push_str(s);
1792
- for _ in 0..right_pad {
1793
- result.push(fillchar);
1794
- }
1795
- result
1796
- };
1797
-
1798
- allocate_string(result, vm.heap)
1799
- }
1800
-
1801
- /// Implements Python's `str.ljust(width, fillchar?)` method.
1802
- ///
1803
- /// Returns left-justified in a string of length width.
1804
- fn str_ljust(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1805
- let (width, fillchar) = parse_justify_args("str.ljust", args, vm)?;
1806
- let len = s.chars().count();
1807
-
1808
- let result = if width <= len {
1809
- s.to_owned()
1810
- } else {
1811
- check_repeat_size(width, fillchar.len_utf8(), vm.heap.tracker())?;
1812
- let pad = width - len;
1813
- let mut result = String::with_capacity(width);
1814
- result.push_str(s);
1815
- for _ in 0..pad {
1816
- result.push(fillchar);
1817
- }
1818
- result
1819
- };
1820
-
1821
- allocate_string(result, vm.heap)
1822
- }
1823
-
1824
- /// Implements Python's `str.rjust(width, fillchar?)` method.
1825
- ///
1826
- /// Returns right-justified in a string of length width.
1827
- fn str_rjust(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1828
- let (width, fillchar) = parse_justify_args("str.rjust", args, vm)?;
1829
- let len = s.chars().count();
1830
-
1831
- let result = if width <= len {
1832
- s.to_owned()
1833
- } else {
1834
- check_repeat_size(width, fillchar.len_utf8(), vm.heap.tracker())?;
1835
- let pad = width - len;
1836
- let mut result = String::with_capacity(width);
1837
- for _ in 0..pad {
1838
- result.push(fillchar);
1839
- }
1840
- result.push_str(s);
1841
- result
1842
- };
1843
-
1844
- allocate_string(result, vm.heap)
1845
- }
1846
-
1847
- /// Parses arguments for justify methods (center, ljust, rjust).
1848
- fn parse_justify_args(
1849
- method: &str,
1850
- args: ArgValues,
1851
- vm: &mut VM<'_, '_, impl ResourceTracker>,
1852
- ) -> RunResult<(usize, char)> {
1853
- let pos = args.into_pos_only(method, vm.heap)?;
1854
- defer_drop!(pos, vm);
1855
-
1856
- match pos.as_slice() {
1857
- [width_value] => {
1858
- let w = extract_int_arg(width_value, vm.heap)?;
1859
- let width = if w < 0 {
1860
- 0
1861
- } else {
1862
- usize::try_from(w).unwrap_or(usize::MAX)
1863
- };
1864
- Ok((width, ' '))
1865
- }
1866
- [width_value, fillchar_value] => {
1867
- let w = extract_int_arg(width_value, vm.heap)?;
1868
- let width = if w < 0 {
1869
- 0
1870
- } else {
1871
- usize::try_from(w).unwrap_or(usize::MAX)
1872
- };
1873
- let fill_str = extract_string_arg(fillchar_value, vm)?;
1874
- if fill_str.chars().count() != 1 {
1875
- return Err(ExcType::type_error_fillchar_must_be_single_char());
1876
- }
1877
- Ok((width, fill_str.chars().next().unwrap()))
1878
- }
1879
- [] => Err(ExcType::type_error_at_least(method, 1, 0)),
1880
- _ => Err(ExcType::type_error_at_most(method, 2, pos.len())),
1881
- }
1882
- }
1883
-
1884
- /// Implements Python's `str.zfill(width)` method.
1885
- ///
1886
- /// Returns a copy of the string left filled with ASCII '0' digits to make a
1887
- /// string of length width. A sign prefix is handled correctly.
1888
- fn str_zfill(s: &str, args: ArgValues, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
1889
- let width_value = args.get_one_arg("str.zfill", heap)?;
1890
- defer_drop!(width_value, heap);
1891
- let width_i64 = extract_int_arg(width_value, heap)?;
1892
-
1893
- // Safe cast: treat negative as 0, saturate large positive values
1894
- let width = if width_i64 < 0 {
1895
- 0
1896
- } else {
1897
- usize::try_from(width_i64).unwrap_or(usize::MAX)
1898
- };
1899
- let len = s.chars().count();
1900
-
1901
- let result = if width <= len {
1902
- s.to_owned()
1903
- } else {
1904
- // zfill always pads with ASCII '0' (1 byte)
1905
- check_repeat_size(width, 1, heap.tracker())?;
1906
- let pad = width - len;
1907
- let mut chars = s.chars();
1908
- let first = chars.next();
1909
-
1910
- let mut result = String::with_capacity(width);
1911
-
1912
- // Handle sign prefix
1913
- if matches!(first, Some('+' | '-')) {
1914
- result.push(first.unwrap());
1915
- for _ in 0..pad {
1916
- result.push('0');
1917
- }
1918
- result.extend(chars);
1919
- } else {
1920
- for _ in 0..pad {
1921
- result.push('0');
1922
- }
1923
- result.push_str(s);
1924
- }
1925
- result
1926
- };
1927
-
1928
- allocate_string(result, heap)
1929
- }
1930
-
1931
- /// Implements Python's `str.encode(encoding='utf-8', errors='strict')` method.
1932
- ///
1933
- /// Returns an encoded version of the string as a bytes object. Only supports
1934
- /// UTF-8 encoding (the native encoding for Rust strings).
1935
- fn str_encode(s: &str, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
1936
- let (encoding, errors) = parse_encode_args(args, vm)?;
1937
-
1938
- // Only UTF-8 is supported - Rust strings are always valid UTF-8
1939
- let encoding_lower = encoding.to_ascii_lowercase();
1940
- if encoding_lower != "utf-8" && encoding_lower != "utf8" {
1941
- return Err(ExcType::lookup_error_unknown_encoding(&encoding));
1942
- }
1943
-
1944
- // For UTF-8 encoding of a valid UTF-8 string, errors mode doesn't matter
1945
- // since there's nothing to handle - the string is already valid UTF-8
1946
- if errors != "strict" && errors != "ignore" && errors != "replace" && errors != "backslashreplace" {
1947
- return Err(ExcType::lookup_error_unknown_error_handler(&errors));
1948
- }
1949
-
1950
- let bytes = s.as_bytes().to_vec();
1951
- let heap_id = vm.heap.allocate(HeapData::Bytes(Bytes::new(bytes)))?;
1952
- Ok(Value::Ref(heap_id))
1953
- }
1954
-
1955
- /// Parses arguments for `str.encode()`.
1956
- ///
1957
- /// Returns (encoding, errors) with defaults "utf-8" and "strict".
1958
- fn parse_encode_args(args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<(String, String)> {
1959
- let (first, second) = args.get_zero_one_two_args("str.encode", vm.heap)?;
1960
-
1961
- let encoding = if let Some(v) = first {
1962
- defer_drop!(v, vm);
1963
- extract_string_arg(v, vm)?
1964
- } else {
1965
- "utf-8".to_owned()
1966
- };
1967
-
1968
- let errors = if let Some(v) = second {
1969
- defer_drop!(v, vm);
1970
- extract_string_arg(v, vm)?
1971
- } else {
1972
- "strict".to_owned()
1973
- };
1974
-
1975
- Ok((encoding, errors))
1976
- }
1977
-
1978
- /// Implements Python's `str.isidentifier()` predicate.
1979
- ///
1980
- /// Returns True if the string is a valid Python identifier according to
1981
- /// the language definition (starts with letter or underscore, followed by
1982
- /// letters, digits, or underscores). Empty strings return False.
1983
- fn str_isidentifier(s: &str) -> bool {
1984
- if s.is_empty() {
1985
- return false;
1986
- }
1987
-
1988
- let mut chars = s.chars();
1989
-
1990
- // First character must be a letter (Unicode) or underscore
1991
- let first = chars.next().unwrap();
1992
- if !is_xid_start(first) && first != '_' {
1993
- return false;
1994
- }
1995
-
1996
- // Remaining characters must be letters, digits (Unicode), or underscores
1997
- chars.all(is_xid_continue)
1998
- }
1999
-
2000
- /// Checks if a character is valid at the start of an identifier (XID_Start).
2001
- ///
2002
- /// This is a simplified implementation that covers ASCII and common Unicode letters.
2003
- /// Python uses the full Unicode XID_Start property.
2004
- fn is_xid_start(c: char) -> bool {
2005
- c.is_alphabetic()
2006
- }
2007
-
2008
- /// Checks if a character is valid in the continuation of an identifier (XID_Continue).
2009
- ///
2010
- /// This is a simplified implementation that covers ASCII and common Unicode.
2011
- /// Python uses the full Unicode XID_Continue property.
2012
- fn is_xid_continue(c: char) -> bool {
2013
- c.is_alphanumeric() || c == '_'
2014
- }
2015
-
2016
- /// Implements Python's `str.istitle()` predicate.
2017
- ///
2018
- /// Returns True if the string is titlecased: uppercase characters follow
2019
- /// uncased characters and lowercase characters follow cased characters.
2020
- /// Empty strings return False.
2021
- fn str_istitle(s: &str) -> bool {
2022
- if s.is_empty() {
2023
- return false;
2024
- }
2025
-
2026
- let mut prev_cased = false;
2027
- let mut has_cased = false;
2028
-
2029
- for c in s.chars() {
2030
- if c.is_uppercase() {
2031
- // Uppercase must follow uncased
2032
- if prev_cased {
2033
- return false;
2034
- }
2035
- prev_cased = true;
2036
- has_cased = true;
2037
- } else if c.is_lowercase() {
2038
- // Lowercase must follow cased
2039
- if !prev_cased {
2040
- return false;
2041
- }
2042
- prev_cased = true;
2043
- has_cased = true;
2044
- } else {
2045
- // Uncased character
2046
- prev_cased = false;
2047
- }
2048
- }
2049
-
2050
- has_cased
2051
- }