superacli 1.1.4 → 1.1.6

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 (961) hide show
  1. package/__tests__/adapter-schema.test.js +2 -0
  2. package/__tests__/config.test.js +62 -1
  3. package/__tests__/help-json.test.js +2 -0
  4. package/__tests__/mcp-adapter.test.js +14 -4
  5. package/__tests__/mcp-local.test.js +159 -0
  6. package/__tests__/mcp-stdio-jsonrpc.test.js +105 -0
  7. package/__tests__/monty-plugin.test.js +121 -0
  8. package/__tests__/plugin-browser-use-uninstall.test.js +23 -0
  9. package/__tests__/plugin-browser-use.test.js +77 -0
  10. package/__tests__/plugins-command.test.js +92 -1
  11. package/__tests__/plugins-learn.test.js +62 -0
  12. package/__tests__/plugins-registry.test.js +3 -1
  13. package/__tests__/resend-plugin.test.js +122 -0
  14. package/__tests__/skills.test.js +4 -0
  15. package/cli/adapter-schema.js +3 -2
  16. package/cli/adapters/mcp.js +22 -3
  17. package/cli/adapters/process.js +34 -7
  18. package/cli/config.js +27 -1
  19. package/cli/help-json.js +2 -2
  20. package/cli/mcp-diagnostics.js +152 -0
  21. package/cli/mcp-discovery.js +221 -0
  22. package/cli/mcp-local.js +267 -25
  23. package/cli/mcp-stdio-jsonrpc.js +246 -0
  24. package/cli/plugin-install-guidance.js +25 -0
  25. package/cli/plugins-command.js +86 -3
  26. package/cli/plugins-learn.js +177 -0
  27. package/cli/plugins-manager.js +3 -0
  28. package/cli/plugins-registry.js +2 -1
  29. package/cli/skills-mcp.js +102 -0
  30. package/cli/skills.js +6 -40
  31. package/cli/supercli.js +7 -2
  32. package/docs/initial/mcp-local-mode.md +35 -0
  33. package/docs/mcp-cheatsheet.md +324 -0
  34. package/docs/plugins.md +7 -0
  35. package/package.json +1 -1
  36. package/plugins/browser-use/plugin.json +23 -0
  37. package/plugins/browser-use/scripts/post-install.js +146 -0
  38. package/plugins/browser-use/scripts/post-uninstall.js +28 -0
  39. package/plugins/browser-use/skills/quickstart/SKILL.md +47 -0
  40. package/plugins/monty/README.md +49 -0
  41. package/plugins/monty/plugin.json +69 -0
  42. package/plugins/monty/scripts/post-install.js +73 -0
  43. package/plugins/monty/scripts/post-uninstall.js +23 -0
  44. package/plugins/monty/scripts/run-python.js +140 -0
  45. package/plugins/monty/scripts/setup-monty.js +27 -0
  46. package/plugins/plugins.json +29 -0
  47. package/plugins/resend/plugin.json +371 -0
  48. package/plugins/resend/scripts/post-install.js +59 -0
  49. package/plugins/resend/scripts/post-uninstall.js +23 -0
  50. package/plugins/resend/scripts/setup-resend.js +27 -0
  51. package/plugins/resend/skills/quickstart/SKILL.md +80 -0
  52. package/ref-monty/.cargo/config.toml +3 -0
  53. package/ref-monty/.claude/settings.json +60 -0
  54. package/ref-monty/.claude/skills/fastmod/SKILL.md +22 -0
  55. package/ref-monty/.claude/skills/python-playground/SKILL.md +47 -0
  56. package/ref-monty/.codecov.yml +12 -0
  57. package/ref-monty/.github/actions/build-pgo-wheel/action.yml +72 -0
  58. package/ref-monty/.github/workflows/ci.yml +776 -0
  59. package/ref-monty/.github/workflows/codspeed.yml +45 -0
  60. package/ref-monty/.github/workflows/init-npm-packages.yml +82 -0
  61. package/ref-monty/.pre-commit-config.yaml +47 -0
  62. package/ref-monty/.python-version +1 -0
  63. package/ref-monty/.rustfmt.toml +4 -0
  64. package/ref-monty/.zed/settings.json +11 -0
  65. package/ref-monty/CLAUDE.md +535 -0
  66. package/ref-monty/Cargo.lock +3798 -0
  67. package/ref-monty/Cargo.toml +87 -0
  68. package/ref-monty/LICENSE +21 -0
  69. package/ref-monty/Makefile +216 -0
  70. package/ref-monty/README.md +430 -0
  71. package/ref-monty/RELEASING.md +47 -0
  72. package/ref-monty/crates/fuzz/Cargo.toml +30 -0
  73. package/ref-monty/crates/fuzz/fuzz_targets/string_input_panic.rs +37 -0
  74. package/ref-monty/crates/fuzz/fuzz_targets/tokens_input_panic.rs +552 -0
  75. package/ref-monty/crates/monty/Cargo.toml +68 -0
  76. package/ref-monty/crates/monty/benches/main.rs +247 -0
  77. package/ref-monty/crates/monty/build.rs +10 -0
  78. package/ref-monty/crates/monty/src/args.rs +733 -0
  79. package/ref-monty/crates/monty/src/asyncio.rs +179 -0
  80. package/ref-monty/crates/monty/src/builtins/abs.rs +55 -0
  81. package/ref-monty/crates/monty/src/builtins/all.rs +30 -0
  82. package/ref-monty/crates/monty/src/builtins/any.rs +30 -0
  83. package/ref-monty/crates/monty/src/builtins/bin.rs +59 -0
  84. package/ref-monty/crates/monty/src/builtins/chr.rs +46 -0
  85. package/ref-monty/crates/monty/src/builtins/divmod.rs +164 -0
  86. package/ref-monty/crates/monty/src/builtins/enumerate.rs +52 -0
  87. package/ref-monty/crates/monty/src/builtins/filter.rs +67 -0
  88. package/ref-monty/crates/monty/src/builtins/getattr.rs +65 -0
  89. package/ref-monty/crates/monty/src/builtins/hash.rs +28 -0
  90. package/ref-monty/crates/monty/src/builtins/hex.rs +58 -0
  91. package/ref-monty/crates/monty/src/builtins/id.rs +24 -0
  92. package/ref-monty/crates/monty/src/builtins/isinstance.rs +68 -0
  93. package/ref-monty/crates/monty/src/builtins/len.rs +25 -0
  94. package/ref-monty/crates/monty/src/builtins/map.rs +98 -0
  95. package/ref-monty/crates/monty/src/builtins/min_max.rs +113 -0
  96. package/ref-monty/crates/monty/src/builtins/mod.rs +246 -0
  97. package/ref-monty/crates/monty/src/builtins/next.rs +21 -0
  98. package/ref-monty/crates/monty/src/builtins/oct.rs +59 -0
  99. package/ref-monty/crates/monty/src/builtins/ord.rs +67 -0
  100. package/ref-monty/crates/monty/src/builtins/pow.rs +365 -0
  101. package/ref-monty/crates/monty/src/builtins/print.rs +141 -0
  102. package/ref-monty/crates/monty/src/builtins/repr.rs +16 -0
  103. package/ref-monty/crates/monty/src/builtins/reversed.rs +28 -0
  104. package/ref-monty/crates/monty/src/builtins/round.rs +174 -0
  105. package/ref-monty/crates/monty/src/builtins/sorted.rs +151 -0
  106. package/ref-monty/crates/monty/src/builtins/sum.rs +66 -0
  107. package/ref-monty/crates/monty/src/builtins/type_.rs +16 -0
  108. package/ref-monty/crates/monty/src/builtins/zip.rs +77 -0
  109. package/ref-monty/crates/monty/src/bytecode/builder.rs +699 -0
  110. package/ref-monty/crates/monty/src/bytecode/code.rs +310 -0
  111. package/ref-monty/crates/monty/src/bytecode/compiler.rs +3206 -0
  112. package/ref-monty/crates/monty/src/bytecode/mod.rs +24 -0
  113. package/ref-monty/crates/monty/src/bytecode/op.rs +617 -0
  114. package/ref-monty/crates/monty/src/bytecode/vm/async_exec.rs +1058 -0
  115. package/ref-monty/crates/monty/src/bytecode/vm/attr.rs +63 -0
  116. package/ref-monty/crates/monty/src/bytecode/vm/binary.rs +487 -0
  117. package/ref-monty/crates/monty/src/bytecode/vm/call.rs +767 -0
  118. package/ref-monty/crates/monty/src/bytecode/vm/collections.rs +741 -0
  119. package/ref-monty/crates/monty/src/bytecode/vm/compare.rs +147 -0
  120. package/ref-monty/crates/monty/src/bytecode/vm/exceptions.rs +297 -0
  121. package/ref-monty/crates/monty/src/bytecode/vm/format.rs +132 -0
  122. package/ref-monty/crates/monty/src/bytecode/vm/mod.rs +1958 -0
  123. package/ref-monty/crates/monty/src/bytecode/vm/scheduler.rs +620 -0
  124. package/ref-monty/crates/monty/src/exception_private.rs +1513 -0
  125. package/ref-monty/crates/monty/src/exception_public.rs +346 -0
  126. package/ref-monty/crates/monty/src/expressions.rs +694 -0
  127. package/ref-monty/crates/monty/src/fstring.rs +854 -0
  128. package/ref-monty/crates/monty/src/function.rs +119 -0
  129. package/ref-monty/crates/monty/src/heap.rs +1073 -0
  130. package/ref-monty/crates/monty/src/heap_data.rs +985 -0
  131. package/ref-monty/crates/monty/src/heap_traits.rs +312 -0
  132. package/ref-monty/crates/monty/src/intern.rs +837 -0
  133. package/ref-monty/crates/monty/src/io.rs +106 -0
  134. package/ref-monty/crates/monty/src/lib.rs +52 -0
  135. package/ref-monty/crates/monty/src/modules/asyncio.rs +144 -0
  136. package/ref-monty/crates/monty/src/modules/math.rs +1453 -0
  137. package/ref-monty/crates/monty/src/modules/mod.rs +120 -0
  138. package/ref-monty/crates/monty/src/modules/os.rs +116 -0
  139. package/ref-monty/crates/monty/src/modules/pathlib.rs +33 -0
  140. package/ref-monty/crates/monty/src/modules/re.rs +606 -0
  141. package/ref-monty/crates/monty/src/modules/sys.rs +60 -0
  142. package/ref-monty/crates/monty/src/modules/typing.rs +70 -0
  143. package/ref-monty/crates/monty/src/namespace.rs +21 -0
  144. package/ref-monty/crates/monty/src/object.rs +1040 -0
  145. package/ref-monty/crates/monty/src/os.rs +215 -0
  146. package/ref-monty/crates/monty/src/parse.rs +1730 -0
  147. package/ref-monty/crates/monty/src/prepare.rs +3015 -0
  148. package/ref-monty/crates/monty/src/repl.rs +1109 -0
  149. package/ref-monty/crates/monty/src/resource.rs +559 -0
  150. package/ref-monty/crates/monty/src/run.rs +457 -0
  151. package/ref-monty/crates/monty/src/run_progress.rs +821 -0
  152. package/ref-monty/crates/monty/src/signature.rs +651 -0
  153. package/ref-monty/crates/monty/src/sorting.rs +100 -0
  154. package/ref-monty/crates/monty/src/types/bytes.rs +2356 -0
  155. package/ref-monty/crates/monty/src/types/dataclass.rs +345 -0
  156. package/ref-monty/crates/monty/src/types/dict.rs +879 -0
  157. package/ref-monty/crates/monty/src/types/dict_view.rs +619 -0
  158. package/ref-monty/crates/monty/src/types/iter.rs +799 -0
  159. package/ref-monty/crates/monty/src/types/list.rs +929 -0
  160. package/ref-monty/crates/monty/src/types/long_int.rs +211 -0
  161. package/ref-monty/crates/monty/src/types/mod.rs +48 -0
  162. package/ref-monty/crates/monty/src/types/module.rs +146 -0
  163. package/ref-monty/crates/monty/src/types/namedtuple.rs +261 -0
  164. package/ref-monty/crates/monty/src/types/path.rs +596 -0
  165. package/ref-monty/crates/monty/src/types/property.rs +35 -0
  166. package/ref-monty/crates/monty/src/types/py_trait.rs +322 -0
  167. package/ref-monty/crates/monty/src/types/range.rs +285 -0
  168. package/ref-monty/crates/monty/src/types/re_match.rs +522 -0
  169. package/ref-monty/crates/monty/src/types/re_pattern.rs +726 -0
  170. package/ref-monty/crates/monty/src/types/set.rs +1373 -0
  171. package/ref-monty/crates/monty/src/types/slice.rs +257 -0
  172. package/ref-monty/crates/monty/src/types/str.rs +2051 -0
  173. package/ref-monty/crates/monty/src/types/tuple.rs +376 -0
  174. package/ref-monty/crates/monty/src/types/type.rs +407 -0
  175. package/ref-monty/crates/monty/src/value.rs +2558 -0
  176. package/ref-monty/crates/monty/test_cases/args__dict_get_no_args.py +3 -0
  177. package/ref-monty/crates/monty/test_cases/args__dict_get_too_many.py +3 -0
  178. package/ref-monty/crates/monty/test_cases/args__dict_items_with_args.py +3 -0
  179. package/ref-monty/crates/monty/test_cases/args__dict_keys_with_args.py +3 -0
  180. package/ref-monty/crates/monty/test_cases/args__dict_pop_no_args.py +3 -0
  181. package/ref-monty/crates/monty/test_cases/args__dict_pop_too_many.py +3 -0
  182. package/ref-monty/crates/monty/test_cases/args__dict_values_with_args.py +3 -0
  183. package/ref-monty/crates/monty/test_cases/args__id_too_many.py +2 -0
  184. package/ref-monty/crates/monty/test_cases/args__len_no_args.py +2 -0
  185. package/ref-monty/crates/monty/test_cases/args__len_too_many.py +2 -0
  186. package/ref-monty/crates/monty/test_cases/args__len_type_error_int.py +9 -0
  187. package/ref-monty/crates/monty/test_cases/args__len_type_error_none.py +9 -0
  188. package/ref-monty/crates/monty/test_cases/args__list_append_no_args.py +3 -0
  189. package/ref-monty/crates/monty/test_cases/args__list_append_too_many.py +3 -0
  190. package/ref-monty/crates/monty/test_cases/args__list_insert_too_few.py +3 -0
  191. package/ref-monty/crates/monty/test_cases/args__list_insert_too_many.py +3 -0
  192. package/ref-monty/crates/monty/test_cases/args__repr_no_args.py +2 -0
  193. package/ref-monty/crates/monty/test_cases/arith__div_zero_float.py +2 -0
  194. package/ref-monty/crates/monty/test_cases/arith__div_zero_int.py +2 -0
  195. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_float.py +2 -0
  196. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_int.py +2 -0
  197. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg.py +2 -0
  198. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg_builtin.py +9 -0
  199. package/ref-monty/crates/monty/test_cases/assert__expr_fail.py +2 -0
  200. package/ref-monty/crates/monty/test_cases/assert__fail.py +2 -0
  201. package/ref-monty/crates/monty/test_cases/assert__fail_msg.py +2 -0
  202. package/ref-monty/crates/monty/test_cases/assert__fn_fail.py +3 -0
  203. package/ref-monty/crates/monty/test_cases/assert__ops.py +11 -0
  204. package/ref-monty/crates/monty/test_cases/async__asyncio_run.py +47 -0
  205. package/ref-monty/crates/monty/test_cases/async__basic.py +10 -0
  206. package/ref-monty/crates/monty/test_cases/async__closure.py +14 -0
  207. package/ref-monty/crates/monty/test_cases/async__double_await_coroutine.py +16 -0
  208. package/ref-monty/crates/monty/test_cases/async__exception.py +10 -0
  209. package/ref-monty/crates/monty/test_cases/async__ext_call.py +73 -0
  210. package/ref-monty/crates/monty/test_cases/async__gather_all.py +85 -0
  211. package/ref-monty/crates/monty/test_cases/async__nested_await.py +15 -0
  212. package/ref-monty/crates/monty/test_cases/async__nested_gather_ext.py +37 -0
  213. package/ref-monty/crates/monty/test_cases/async__not_awaitable.py +10 -0
  214. package/ref-monty/crates/monty/test_cases/async__not_imported.py +14 -0
  215. package/ref-monty/crates/monty/test_cases/async__recursion_depth_isolation.py +27 -0
  216. package/ref-monty/crates/monty/test_cases/async__return_types.py +31 -0
  217. package/ref-monty/crates/monty/test_cases/async__sequential.py +16 -0
  218. package/ref-monty/crates/monty/test_cases/async__traceback.py +19 -0
  219. package/ref-monty/crates/monty/test_cases/async__with_args.py +14 -0
  220. package/ref-monty/crates/monty/test_cases/attr__get_int_error.py +9 -0
  221. package/ref-monty/crates/monty/test_cases/attr__get_list_error.py +9 -0
  222. package/ref-monty/crates/monty/test_cases/attr__set_frozen_nonfield.py +12 -0
  223. package/ref-monty/crates/monty/test_cases/attr__set_int_error.py +10 -0
  224. package/ref-monty/crates/monty/test_cases/attr__set_list_error.py +10 -0
  225. package/ref-monty/crates/monty/test_cases/bench__kitchen_sink.py +68 -0
  226. package/ref-monty/crates/monty/test_cases/bool__ops.py +20 -0
  227. package/ref-monty/crates/monty/test_cases/builtin__add_type_error.py +2 -0
  228. package/ref-monty/crates/monty/test_cases/builtin__filter.py +62 -0
  229. package/ref-monty/crates/monty/test_cases/builtin__filter_not_iterable.py +11 -0
  230. package/ref-monty/crates/monty/test_cases/builtin__getattr.py +84 -0
  231. package/ref-monty/crates/monty/test_cases/builtin__iter_funcs.py +42 -0
  232. package/ref-monty/crates/monty/test_cases/builtin__iter_next.py +66 -0
  233. package/ref-monty/crates/monty/test_cases/builtin__map.py +74 -0
  234. package/ref-monty/crates/monty/test_cases/builtin__map_not_iterable.py +11 -0
  235. package/ref-monty/crates/monty/test_cases/builtin__math_funcs.py +154 -0
  236. package/ref-monty/crates/monty/test_cases/builtin__more_iter_funcs.py +148 -0
  237. package/ref-monty/crates/monty/test_cases/builtin__next_stop_iteration.py +10 -0
  238. package/ref-monty/crates/monty/test_cases/builtin__print_invalid_kwarg.py +9 -0
  239. package/ref-monty/crates/monty/test_cases/builtin__print_kwargs.py +12 -0
  240. package/ref-monty/crates/monty/test_cases/builtin__repr.py +3 -0
  241. package/ref-monty/crates/monty/test_cases/builtin__string_funcs.py +73 -0
  242. package/ref-monty/crates/monty/test_cases/bytes__decode_invalid_utf8.py +18 -0
  243. package/ref-monty/crates/monty/test_cases/bytes__endswith_str_error.py +10 -0
  244. package/ref-monty/crates/monty/test_cases/bytes__getitem_index_error.py +10 -0
  245. package/ref-monty/crates/monty/test_cases/bytes__index_start_gt_end.py +10 -0
  246. package/ref-monty/crates/monty/test_cases/bytes__methods.py +394 -0
  247. package/ref-monty/crates/monty/test_cases/bytes__negative_count.py +9 -0
  248. package/ref-monty/crates/monty/test_cases/bytes__ops.py +90 -0
  249. package/ref-monty/crates/monty/test_cases/bytes__startswith_str_error.py +10 -0
  250. package/ref-monty/crates/monty/test_cases/call_object.py +3 -0
  251. package/ref-monty/crates/monty/test_cases/chain_comparison__all.py +79 -0
  252. package/ref-monty/crates/monty/test_cases/closure__param_shadows_outer.py +81 -0
  253. package/ref-monty/crates/monty/test_cases/closure__pep448.py +203 -0
  254. package/ref-monty/crates/monty/test_cases/closure__undefined_nonlocal.py +13 -0
  255. package/ref-monty/crates/monty/test_cases/compare__mixed_types.py +120 -0
  256. package/ref-monty/crates/monty/test_cases/comprehension__all.py +208 -0
  257. package/ref-monty/crates/monty/test_cases/comprehension__scope.py +7 -0
  258. package/ref-monty/crates/monty/test_cases/comprehension__unbound_local.py +14 -0
  259. package/ref-monty/crates/monty/test_cases/dataclass__basic.py +238 -0
  260. package/ref-monty/crates/monty/test_cases/dataclass__call_field_error.py +12 -0
  261. package/ref-monty/crates/monty/test_cases/dataclass__frozen_set_error.py +12 -0
  262. package/ref-monty/crates/monty/test_cases/dataclass__get_missing_attr_error.py +11 -0
  263. package/ref-monty/crates/monty/test_cases/dict__get_unhashable_key.py +3 -0
  264. package/ref-monty/crates/monty/test_cases/dict__literal_unhashable_key.py +2 -0
  265. package/ref-monty/crates/monty/test_cases/dict__method_pop_missing_error.py +3 -0
  266. package/ref-monty/crates/monty/test_cases/dict__methods.py +151 -0
  267. package/ref-monty/crates/monty/test_cases/dict__ops.py +133 -0
  268. package/ref-monty/crates/monty/test_cases/dict__pop_unhashable_key.py +4 -0
  269. package/ref-monty/crates/monty/test_cases/dict__popitem_empty.py +9 -0
  270. package/ref-monty/crates/monty/test_cases/dict__subscript_missing_key.py +3 -0
  271. package/ref-monty/crates/monty/test_cases/dict__unhashable_dict_key.py +2 -0
  272. package/ref-monty/crates/monty/test_cases/dict__unhashable_list_key.py +2 -0
  273. package/ref-monty/crates/monty/test_cases/dict__unpack_type_error.py +2 -0
  274. package/ref-monty/crates/monty/test_cases/dict__views.py +165 -0
  275. package/ref-monty/crates/monty/test_cases/edge__all.py +26 -0
  276. package/ref-monty/crates/monty/test_cases/edge__float_int_mod.py +2 -0
  277. package/ref-monty/crates/monty/test_cases/edge__int_float_mod.py +2 -0
  278. package/ref-monty/crates/monty/test_cases/exc__args.py +16 -0
  279. package/ref-monty/crates/monty/test_cases/exc__str.py +15 -0
  280. package/ref-monty/crates/monty/test_cases/execute_ok__all.py +54 -0
  281. package/ref-monty/crates/monty/test_cases/execute_raise__error_instance_str.py +2 -0
  282. package/ref-monty/crates/monty/test_cases/execute_raise__error_no_args.py +2 -0
  283. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg.py +2 -0
  284. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg_quotes.py +2 -0
  285. package/ref-monty/crates/monty/test_cases/execute_raise__error_type.py +2 -0
  286. package/ref-monty/crates/monty/test_cases/execute_raise__raise_instance_via_var.py +4 -0
  287. package/ref-monty/crates/monty/test_cases/execute_raise__raise_list.py +2 -0
  288. package/ref-monty/crates/monty/test_cases/execute_raise__raise_number.py +2 -0
  289. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_call_via_var.py +4 -0
  290. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_direct.py +3 -0
  291. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_via_var.py +4 -0
  292. package/ref-monty/crates/monty/test_cases/ext_call__arg_side_effect_bug.py +22 -0
  293. package/ref-monty/crates/monty/test_cases/ext_call__augmented.py +17 -0
  294. package/ref-monty/crates/monty/test_cases/ext_call__augmented_refcount_bug.py +7 -0
  295. package/ref-monty/crates/monty/test_cases/ext_call__bare_raise_after_resume.py +34 -0
  296. package/ref-monty/crates/monty/test_cases/ext_call__basic.py +99 -0
  297. package/ref-monty/crates/monty/test_cases/ext_call__boolean.py +37 -0
  298. package/ref-monty/crates/monty/test_cases/ext_call__boolean_side_effect_hang.py +17 -0
  299. package/ref-monty/crates/monty/test_cases/ext_call__closure_bug.py +16 -0
  300. package/ref-monty/crates/monty/test_cases/ext_call__comparison.py +26 -0
  301. package/ref-monty/crates/monty/test_cases/ext_call__deep_call_stack.py +18 -0
  302. package/ref-monty/crates/monty/test_cases/ext_call__elif.py +171 -0
  303. package/ref-monty/crates/monty/test_cases/ext_call__exc.py +4 -0
  304. package/ref-monty/crates/monty/test_cases/ext_call__exc_deep_stack.py +39 -0
  305. package/ref-monty/crates/monty/test_cases/ext_call__exc_in_function.py +17 -0
  306. package/ref-monty/crates/monty/test_cases/ext_call__exc_nested_functions.py +31 -0
  307. package/ref-monty/crates/monty/test_cases/ext_call__ext_exc.py +171 -0
  308. package/ref-monty/crates/monty/test_cases/ext_call__for.py +114 -0
  309. package/ref-monty/crates/monty/test_cases/ext_call__fstring.py +12 -0
  310. package/ref-monty/crates/monty/test_cases/ext_call__if.py +135 -0
  311. package/ref-monty/crates/monty/test_cases/ext_call__if_condition.py +37 -0
  312. package/ref-monty/crates/monty/test_cases/ext_call__in_closure.py +14 -0
  313. package/ref-monty/crates/monty/test_cases/ext_call__in_function.py +40 -0
  314. package/ref-monty/crates/monty/test_cases/ext_call__in_function_simple.py +7 -0
  315. package/ref-monty/crates/monty/test_cases/ext_call__literals.py +17 -0
  316. package/ref-monty/crates/monty/test_cases/ext_call__multi_in_func.py +32 -0
  317. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup.py +69 -0
  318. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup_undefined.py +4 -0
  319. package/ref-monty/crates/monty/test_cases/ext_call__nested_calls.py +14 -0
  320. package/ref-monty/crates/monty/test_cases/ext_call__recursion_bug.py +19 -0
  321. package/ref-monty/crates/monty/test_cases/ext_call__return.py +28 -0
  322. package/ref-monty/crates/monty/test_cases/ext_call__side_effects.py +25 -0
  323. package/ref-monty/crates/monty/test_cases/ext_call__subscript.py +7 -0
  324. package/ref-monty/crates/monty/test_cases/ext_call__ternary.py +28 -0
  325. package/ref-monty/crates/monty/test_cases/ext_call__try.py +280 -0
  326. package/ref-monty/crates/monty/test_cases/ext_call__try_simple.py +10 -0
  327. package/ref-monty/crates/monty/test_cases/ext_call__unary.py +13 -0
  328. package/ref-monty/crates/monty/test_cases/frozenset__ops.py +178 -0
  329. package/ref-monty/crates/monty/test_cases/fstring__all.py +236 -0
  330. package/ref-monty/crates/monty/test_cases/fstring__error_eq_align_on_str.py +3 -0
  331. package/ref-monty/crates/monty/test_cases/fstring__error_float_f_on_str.py +3 -0
  332. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_float.py +3 -0
  333. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_str.py +3 -0
  334. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec.py +4 -0
  335. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_dynamic.py +4 -0
  336. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_str.py +4 -0
  337. package/ref-monty/crates/monty/test_cases/fstring__error_str_s_on_int.py +3 -0
  338. package/ref-monty/crates/monty/test_cases/function__call_duplicate_kwargs.py +6 -0
  339. package/ref-monty/crates/monty/test_cases/function__call_unpack.py +42 -0
  340. package/ref-monty/crates/monty/test_cases/function__defaults.py +117 -0
  341. package/ref-monty/crates/monty/test_cases/function__err_duplicate_arg.py +7 -0
  342. package/ref-monty/crates/monty/test_cases/function__err_duplicate_first_arg.py +7 -0
  343. package/ref-monty/crates/monty/test_cases/function__err_duplicate_kwarg_cleanup.py +9 -0
  344. package/ref-monty/crates/monty/test_cases/function__err_kwonly_as_positional.py +7 -0
  345. package/ref-monty/crates/monty/test_cases/function__err_missing_all_posonly.py +7 -0
  346. package/ref-monty/crates/monty/test_cases/function__err_missing_heap_cleanup.py +9 -0
  347. package/ref-monty/crates/monty/test_cases/function__err_missing_kwonly.py +7 -0
  348. package/ref-monty/crates/monty/test_cases/function__err_missing_posonly_with_kwarg.py +7 -0
  349. package/ref-monty/crates/monty/test_cases/function__err_missing_with_posonly.py +7 -0
  350. package/ref-monty/crates/monty/test_cases/function__err_posonly_as_kwarg.py +7 -0
  351. package/ref-monty/crates/monty/test_cases/function__err_posonly_first_as_kwarg.py +7 -0
  352. package/ref-monty/crates/monty/test_cases/function__err_too_many_posonly.py +7 -0
  353. package/ref-monty/crates/monty/test_cases/function__err_too_many_with_kwonly.py +7 -0
  354. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg.py +7 -0
  355. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_cleanup.py +9 -0
  356. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_quote.py +13 -0
  357. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_simple.py +7 -0
  358. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_arg.py +6 -0
  359. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_heap.py +8 -0
  360. package/ref-monty/crates/monty/test_cases/function__err_unpack_int.py +6 -0
  361. package/ref-monty/crates/monty/test_cases/function__err_unpack_nonstring_key.py +6 -0
  362. package/ref-monty/crates/monty/test_cases/function__err_unpack_not_mapping.py +6 -0
  363. package/ref-monty/crates/monty/test_cases/function__kwargs_unpacking.py +173 -0
  364. package/ref-monty/crates/monty/test_cases/function__ops.py +294 -0
  365. package/ref-monty/crates/monty/test_cases/function__return_none.py +42 -0
  366. package/ref-monty/crates/monty/test_cases/function__signatures.py +47 -0
  367. package/ref-monty/crates/monty/test_cases/function__too_few_args_all.py +6 -0
  368. package/ref-monty/crates/monty/test_cases/function__too_few_args_one.py +6 -0
  369. package/ref-monty/crates/monty/test_cases/function__too_few_args_two.py +6 -0
  370. package/ref-monty/crates/monty/test_cases/function__too_many_args_one.py +6 -0
  371. package/ref-monty/crates/monty/test_cases/function__too_many_args_two.py +6 -0
  372. package/ref-monty/crates/monty/test_cases/function__too_many_args_zero.py +6 -0
  373. package/ref-monty/crates/monty/test_cases/global__error_assigned_before.py +7 -0
  374. package/ref-monty/crates/monty/test_cases/global__ops.py +163 -0
  375. package/ref-monty/crates/monty/test_cases/hash__dict_unhashable.py +2 -0
  376. package/ref-monty/crates/monty/test_cases/hash__list_unhashable.py +2 -0
  377. package/ref-monty/crates/monty/test_cases/hash__ops.py +153 -0
  378. package/ref-monty/crates/monty/test_cases/id__bytes_literals_distinct.py +3 -0
  379. package/ref-monty/crates/monty/test_cases/id__int_copy_distinct.py +5 -0
  380. package/ref-monty/crates/monty/test_cases/id__is_number_is_number.py +3 -0
  381. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_distinct_types.py +10 -0
  382. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_same_types.py +6 -0
  383. package/ref-monty/crates/monty/test_cases/id__ops.py +97 -0
  384. package/ref-monty/crates/monty/test_cases/id__str_literals_same.py +3 -0
  385. package/ref-monty/crates/monty/test_cases/if__elif_else.py +207 -0
  386. package/ref-monty/crates/monty/test_cases/if__raise_elif.py +11 -0
  387. package/ref-monty/crates/monty/test_cases/if__raise_else.py +13 -0
  388. package/ref-monty/crates/monty/test_cases/if__raise_if.py +9 -0
  389. package/ref-monty/crates/monty/test_cases/if__raise_in_elif_condition.py +18 -0
  390. package/ref-monty/crates/monty/test_cases/if__raise_in_if_condition.py +16 -0
  391. package/ref-monty/crates/monty/test_cases/if_else_expr__all.py +55 -0
  392. package/ref-monty/crates/monty/test_cases/import__error_cannot_import.py +9 -0
  393. package/ref-monty/crates/monty/test_cases/import__error_module_not_found.py +9 -0
  394. package/ref-monty/crates/monty/test_cases/import__local_scope.py +68 -0
  395. package/ref-monty/crates/monty/test_cases/import__os.py +25 -0
  396. package/ref-monty/crates/monty/test_cases/import__relative_error.py +9 -0
  397. package/ref-monty/crates/monty/test_cases/import__relative_no_module_error.py +9 -0
  398. package/ref-monty/crates/monty/test_cases/import__runtime_error_when_executed.py +14 -0
  399. package/ref-monty/crates/monty/test_cases/import__star_error.py +11 -0
  400. package/ref-monty/crates/monty/test_cases/import__sys.py +47 -0
  401. package/ref-monty/crates/monty/test_cases/import__sys_monty.py +28 -0
  402. package/ref-monty/crates/monty/test_cases/import__type_checking_guard.py +37 -0
  403. package/ref-monty/crates/monty/test_cases/import__typing.py +25 -0
  404. package/ref-monty/crates/monty/test_cases/import__typing_type_ignore.py +4 -0
  405. package/ref-monty/crates/monty/test_cases/int__bigint.py +467 -0
  406. package/ref-monty/crates/monty/test_cases/int__bigint_errors.py +260 -0
  407. package/ref-monty/crates/monty/test_cases/int__ops.py +219 -0
  408. package/ref-monty/crates/monty/test_cases/int__overflow_division.py +84 -0
  409. package/ref-monty/crates/monty/test_cases/is_variant__all.py +36 -0
  410. package/ref-monty/crates/monty/test_cases/isinstance__arg2_list_error.py +2 -0
  411. package/ref-monty/crates/monty/test_cases/isinstance__arg2_type_error.py +2 -0
  412. package/ref-monty/crates/monty/test_cases/iter__dict_mutation.py +4 -0
  413. package/ref-monty/crates/monty/test_cases/iter__for.py +243 -0
  414. package/ref-monty/crates/monty/test_cases/iter__for_loop_unpacking.py +66 -0
  415. package/ref-monty/crates/monty/test_cases/iter__generator_expr.py +20 -0
  416. package/ref-monty/crates/monty/test_cases/iter__generator_expr_type.py +7 -0
  417. package/ref-monty/crates/monty/test_cases/iter__not_iterable.py +3 -0
  418. package/ref-monty/crates/monty/test_cases/lambda__all.py +145 -0
  419. package/ref-monty/crates/monty/test_cases/list__extend_not_iterable.py +7 -0
  420. package/ref-monty/crates/monty/test_cases/list__getitem_out_of_bounds.py +3 -0
  421. package/ref-monty/crates/monty/test_cases/list__index_not_found.py +9 -0
  422. package/ref-monty/crates/monty/test_cases/list__index_start_gt_end.py +10 -0
  423. package/ref-monty/crates/monty/test_cases/list__ops.py +473 -0
  424. package/ref-monty/crates/monty/test_cases/list__pop_empty.py +9 -0
  425. package/ref-monty/crates/monty/test_cases/list__pop_out_of_range.py +9 -0
  426. package/ref-monty/crates/monty/test_cases/list__pop_type_error.py +9 -0
  427. package/ref-monty/crates/monty/test_cases/list__remove_not_found.py +9 -0
  428. package/ref-monty/crates/monty/test_cases/list__setitem_dict_index.py +13 -0
  429. package/ref-monty/crates/monty/test_cases/list__setitem_huge_int_index.py +13 -0
  430. package/ref-monty/crates/monty/test_cases/list__setitem_index_error.py +10 -0
  431. package/ref-monty/crates/monty/test_cases/list__setitem_type_error.py +10 -0
  432. package/ref-monty/crates/monty/test_cases/list__unpack_type_error.py +2 -0
  433. package/ref-monty/crates/monty/test_cases/longint__index_error.py +3 -0
  434. package/ref-monty/crates/monty/test_cases/longint__repeat_error.py +3 -0
  435. package/ref-monty/crates/monty/test_cases/loop__break_continue.py +113 -0
  436. package/ref-monty/crates/monty/test_cases/loop__break_finally.py +69 -0
  437. package/ref-monty/crates/monty/test_cases/loop__break_in_function_error.py +13 -0
  438. package/ref-monty/crates/monty/test_cases/loop__break_in_if_error.py +11 -0
  439. package/ref-monty/crates/monty/test_cases/loop__break_nested_except_clears.py +55 -0
  440. package/ref-monty/crates/monty/test_cases/loop__break_outside_error.py +9 -0
  441. package/ref-monty/crates/monty/test_cases/loop__continue_finally.py +81 -0
  442. package/ref-monty/crates/monty/test_cases/loop__continue_in_function_error.py +13 -0
  443. package/ref-monty/crates/monty/test_cases/loop__continue_in_if_error.py +11 -0
  444. package/ref-monty/crates/monty/test_cases/loop__continue_nested_except_clears.py +60 -0
  445. package/ref-monty/crates/monty/test_cases/loop__continue_outside_error.py +9 -0
  446. package/ref-monty/crates/monty/test_cases/math__acos_domain_error.py +11 -0
  447. package/ref-monty/crates/monty/test_cases/math__acosh_domain_error.py +11 -0
  448. package/ref-monty/crates/monty/test_cases/math__asin_domain_error.py +11 -0
  449. package/ref-monty/crates/monty/test_cases/math__atanh_domain_error.py +11 -0
  450. package/ref-monty/crates/monty/test_cases/math__cos_inf_error.py +11 -0
  451. package/ref-monty/crates/monty/test_cases/math__cosh_overflow_error.py +11 -0
  452. package/ref-monty/crates/monty/test_cases/math__exp_overflow_error.py +11 -0
  453. package/ref-monty/crates/monty/test_cases/math__factorial_float_error.py +11 -0
  454. package/ref-monty/crates/monty/test_cases/math__factorial_negative_error.py +11 -0
  455. package/ref-monty/crates/monty/test_cases/math__floor_inf_error.py +11 -0
  456. package/ref-monty/crates/monty/test_cases/math__floor_nan_error.py +11 -0
  457. package/ref-monty/crates/monty/test_cases/math__floor_str_error.py +11 -0
  458. package/ref-monty/crates/monty/test_cases/math__fmod_inf_error.py +11 -0
  459. package/ref-monty/crates/monty/test_cases/math__gamma_neg_int_error.py +11 -0
  460. package/ref-monty/crates/monty/test_cases/math__gcd_float_error.py +11 -0
  461. package/ref-monty/crates/monty/test_cases/math__isqrt_negative_error.py +11 -0
  462. package/ref-monty/crates/monty/test_cases/math__ldexp_overflow_error.py +11 -0
  463. package/ref-monty/crates/monty/test_cases/math__log1p_domain_error.py +11 -0
  464. package/ref-monty/crates/monty/test_cases/math__log_base1_error.py +11 -0
  465. package/ref-monty/crates/monty/test_cases/math__log_zero_error.py +11 -0
  466. package/ref-monty/crates/monty/test_cases/math__module.py +1432 -0
  467. package/ref-monty/crates/monty/test_cases/math__pow_domain_error.py +11 -0
  468. package/ref-monty/crates/monty/test_cases/math__sin_inf_error.py +11 -0
  469. package/ref-monty/crates/monty/test_cases/math__sqrt_negative_error.py +11 -0
  470. package/ref-monty/crates/monty/test_cases/math__tan_inf_error.py +11 -0
  471. package/ref-monty/crates/monty/test_cases/math__trunc_str_error.py +11 -0
  472. package/ref-monty/crates/monty/test_cases/method__args_kwargs_unpacking.py +259 -0
  473. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_func.py +19 -0
  474. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_module.py +12 -0
  475. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_chained.py +9 -0
  476. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_expr.py +9 -0
  477. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_function.py +16 -0
  478. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_with_args.py +9 -0
  479. package/ref-monty/crates/monty/test_cases/name_error__undefined_global.py +10 -0
  480. package/ref-monty/crates/monty/test_cases/namedtuple__missing_attr.py +11 -0
  481. package/ref-monty/crates/monty/test_cases/namedtuple__ops.py +34 -0
  482. package/ref-monty/crates/monty/test_cases/nonlocal__error_module_level.py +3 -0
  483. package/ref-monty/crates/monty/test_cases/nonlocal__ops.py +353 -0
  484. package/ref-monty/crates/monty/test_cases/os__environ.py +40 -0
  485. package/ref-monty/crates/monty/test_cases/os__getenv_key_list_error.py +5 -0
  486. package/ref-monty/crates/monty/test_cases/os__getenv_key_type_error.py +5 -0
  487. package/ref-monty/crates/monty/test_cases/parse_error__complex.py +3 -0
  488. package/ref-monty/crates/monty/test_cases/pathlib__import.py +11 -0
  489. package/ref-monty/crates/monty/test_cases/pathlib__os.py +136 -0
  490. package/ref-monty/crates/monty/test_cases/pathlib__os_read_error.py +12 -0
  491. package/ref-monty/crates/monty/test_cases/pathlib__pure.py +81 -0
  492. package/ref-monty/crates/monty/test_cases/pyobject__cycle_dict_self.py +5 -0
  493. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_dict.py +6 -0
  494. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_self.py +5 -0
  495. package/ref-monty/crates/monty/test_cases/pyobject__cycle_multiple_refs.py +6 -0
  496. package/ref-monty/crates/monty/test_cases/range__error_no_args.py +2 -0
  497. package/ref-monty/crates/monty/test_cases/range__error_step_zero.py +2 -0
  498. package/ref-monty/crates/monty/test_cases/range__error_too_many_args.py +2 -0
  499. package/ref-monty/crates/monty/test_cases/range__getitem_index_error.py +10 -0
  500. package/ref-monty/crates/monty/test_cases/range__ops.py +236 -0
  501. package/ref-monty/crates/monty/test_cases/re__basic.py +756 -0
  502. package/ref-monty/crates/monty/test_cases/re__grouping.py +241 -0
  503. package/ref-monty/crates/monty/test_cases/re__match.py +148 -0
  504. package/ref-monty/crates/monty/test_cases/recursion__deep_drop.py +26 -0
  505. package/ref-monty/crates/monty/test_cases/recursion__deep_eq.py +23 -0
  506. package/ref-monty/crates/monty/test_cases/recursion__deep_hash.py +46 -0
  507. package/ref-monty/crates/monty/test_cases/recursion__deep_repr.py +12 -0
  508. package/ref-monty/crates/monty/test_cases/recursion__function_depth.py +13 -0
  509. package/ref-monty/crates/monty/test_cases/refcount__cycle_mutual_reference.py +18 -0
  510. package/ref-monty/crates/monty/test_cases/refcount__cycle_self_reference.py +12 -0
  511. package/ref-monty/crates/monty/test_cases/refcount__dict_basic.py +5 -0
  512. package/ref-monty/crates/monty/test_cases/refcount__dict_get.py +5 -0
  513. package/ref-monty/crates/monty/test_cases/refcount__dict_keys_and.py +14 -0
  514. package/ref-monty/crates/monty/test_cases/refcount__dict_overwrite.py +6 -0
  515. package/ref-monty/crates/monty/test_cases/refcount__gather_cleanup.py +16 -0
  516. package/ref-monty/crates/monty/test_cases/refcount__gather_exception.py +18 -0
  517. package/ref-monty/crates/monty/test_cases/refcount__gather_nested_cancel.py +25 -0
  518. package/ref-monty/crates/monty/test_cases/refcount__immediate_skipped.py +4 -0
  519. package/ref-monty/crates/monty/test_cases/refcount__kwargs_unpacking.py +27 -0
  520. package/ref-monty/crates/monty/test_cases/refcount__list_append_multiple.py +6 -0
  521. package/ref-monty/crates/monty/test_cases/refcount__list_append_ref.py +5 -0
  522. package/ref-monty/crates/monty/test_cases/refcount__list_concat.py +5 -0
  523. package/ref-monty/crates/monty/test_cases/refcount__list_getitem.py +5 -0
  524. package/ref-monty/crates/monty/test_cases/refcount__list_iadd.py +5 -0
  525. package/ref-monty/crates/monty/test_cases/refcount__nested_list.py +4 -0
  526. package/ref-monty/crates/monty/test_cases/refcount__re_pattern_sub_error_paths.py +37 -0
  527. package/ref-monty/crates/monty/test_cases/refcount__re_search_match.py +34 -0
  528. package/ref-monty/crates/monty/test_cases/refcount__re_sub_error_paths.py +31 -0
  529. package/ref-monty/crates/monty/test_cases/refcount__shared_reference.py +4 -0
  530. package/ref-monty/crates/monty/test_cases/refcount__single_list.py +3 -0
  531. package/ref-monty/crates/monty/test_cases/repr__cycle_detection.py +24 -0
  532. package/ref-monty/crates/monty/test_cases/set__ops.py +191 -0
  533. package/ref-monty/crates/monty/test_cases/set__review_bugs.py +35 -0
  534. package/ref-monty/crates/monty/test_cases/set__unpack_type_error.py +2 -0
  535. package/ref-monty/crates/monty/test_cases/slice__invalid_indices.py +2 -0
  536. package/ref-monty/crates/monty/test_cases/slice__kwargs.py +9 -0
  537. package/ref-monty/crates/monty/test_cases/slice__no_args.py +9 -0
  538. package/ref-monty/crates/monty/test_cases/slice__ops.py +149 -0
  539. package/ref-monty/crates/monty/test_cases/slice__step_zero.py +9 -0
  540. package/ref-monty/crates/monty/test_cases/slice__step_zero_bytes.py +9 -0
  541. package/ref-monty/crates/monty/test_cases/slice__step_zero_range.py +9 -0
  542. package/ref-monty/crates/monty/test_cases/slice__step_zero_str.py +9 -0
  543. package/ref-monty/crates/monty/test_cases/slice__step_zero_tuple.py +9 -0
  544. package/ref-monty/crates/monty/test_cases/slice__too_many_args.py +9 -0
  545. package/ref-monty/crates/monty/test_cases/str__getitem_index_error.py +10 -0
  546. package/ref-monty/crates/monty/test_cases/str__index_not_found.py +9 -0
  547. package/ref-monty/crates/monty/test_cases/str__join_no_args.py +9 -0
  548. package/ref-monty/crates/monty/test_cases/str__join_non_string.py +9 -0
  549. package/ref-monty/crates/monty/test_cases/str__join_not_iterable.py +9 -0
  550. package/ref-monty/crates/monty/test_cases/str__join_too_many_args.py +9 -0
  551. package/ref-monty/crates/monty/test_cases/str__methods.py +327 -0
  552. package/ref-monty/crates/monty/test_cases/str__ops.py +162 -0
  553. package/ref-monty/crates/monty/test_cases/str__partition_empty.py +9 -0
  554. package/ref-monty/crates/monty/test_cases/str__rsplit_empty_sep.py +9 -0
  555. package/ref-monty/crates/monty/test_cases/str__split_empty_sep.py +9 -0
  556. package/ref-monty/crates/monty/test_cases/sys__types.py +7 -0
  557. package/ref-monty/crates/monty/test_cases/traceback__division_error.py +30 -0
  558. package/ref-monty/crates/monty/test_cases/traceback__index_error.py +17 -0
  559. package/ref-monty/crates/monty/test_cases/traceback__insert_as_int.py +10 -0
  560. package/ref-monty/crates/monty/test_cases/traceback__nested_call.py +29 -0
  561. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_module_scope.py +10 -0
  562. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_unbound.py +24 -0
  563. package/ref-monty/crates/monty/test_cases/traceback__range_as_int.py +9 -0
  564. package/ref-monty/crates/monty/test_cases/traceback__recursion_error.py +23 -0
  565. package/ref-monty/crates/monty/test_cases/traceback__set_mutation.py +11 -0
  566. package/ref-monty/crates/monty/test_cases/traceback__undefined_attr_call.py +16 -0
  567. package/ref-monty/crates/monty/test_cases/traceback__undefined_call.py +16 -0
  568. package/ref-monty/crates/monty/test_cases/traceback__undefined_raise.py +16 -0
  569. package/ref-monty/crates/monty/test_cases/try_except__all.py +472 -0
  570. package/ref-monty/crates/monty/test_cases/try_except__bare_raise_no_context.py +2 -0
  571. package/ref-monty/crates/monty/test_cases/try_except__invalid_type.py +5 -0
  572. package/ref-monty/crates/monty/test_cases/tuple__getitem_out_of_bounds.py +3 -0
  573. package/ref-monty/crates/monty/test_cases/tuple__index_not_found.py +9 -0
  574. package/ref-monty/crates/monty/test_cases/tuple__index_start_gt_end.py +10 -0
  575. package/ref-monty/crates/monty/test_cases/tuple__methods.py +19 -0
  576. package/ref-monty/crates/monty/test_cases/tuple__ops.py +133 -0
  577. package/ref-monty/crates/monty/test_cases/tuple__unpack_type_error.py +2 -0
  578. package/ref-monty/crates/monty/test_cases/type__builtin_attr_error.py +9 -0
  579. package/ref-monty/crates/monty/test_cases/type__bytes_negative.py +2 -0
  580. package/ref-monty/crates/monty/test_cases/type__cell_not_builtin.py +9 -0
  581. package/ref-monty/crates/monty/test_cases/type__exception_attr_error.py +11 -0
  582. package/ref-monty/crates/monty/test_cases/type__float_conversion_error.py +2 -0
  583. package/ref-monty/crates/monty/test_cases/type__float_repr_both_quotes.py +9 -0
  584. package/ref-monty/crates/monty/test_cases/type__float_repr_newline.py +9 -0
  585. package/ref-monty/crates/monty/test_cases/type__float_repr_single_quote.py +9 -0
  586. package/ref-monty/crates/monty/test_cases/type__int_conversion_error.py +2 -0
  587. package/ref-monty/crates/monty/test_cases/type__list_not_iterable.py +2 -0
  588. package/ref-monty/crates/monty/test_cases/type__non_builtin_name_error.py +9 -0
  589. package/ref-monty/crates/monty/test_cases/type__ops.py +200 -0
  590. package/ref-monty/crates/monty/test_cases/type__shadow_exc.py +3 -0
  591. package/ref-monty/crates/monty/test_cases/type__shadow_int.py +9 -0
  592. package/ref-monty/crates/monty/test_cases/type__shadow_len.py +3 -0
  593. package/ref-monty/crates/monty/test_cases/type__tuple_not_iterable.py +2 -0
  594. package/ref-monty/crates/monty/test_cases/type_error__int_add_list.py +2 -0
  595. package/ref-monty/crates/monty/test_cases/type_error__int_div_str.py +2 -0
  596. package/ref-monty/crates/monty/test_cases/type_error__int_floordiv_str.py +2 -0
  597. package/ref-monty/crates/monty/test_cases/type_error__int_iadd_str.py +3 -0
  598. package/ref-monty/crates/monty/test_cases/type_error__int_mod_str.py +2 -0
  599. package/ref-monty/crates/monty/test_cases/type_error__int_pow_str.py +2 -0
  600. package/ref-monty/crates/monty/test_cases/type_error__int_sub_str.py +2 -0
  601. package/ref-monty/crates/monty/test_cases/type_error__list_add_int.py +2 -0
  602. package/ref-monty/crates/monty/test_cases/type_error__list_add_str.py +2 -0
  603. package/ref-monty/crates/monty/test_cases/type_error__list_iadd_int.py +6 -0
  604. package/ref-monty/crates/monty/test_cases/type_error__str_add_int.py +2 -0
  605. package/ref-monty/crates/monty/test_cases/type_error__str_iadd_int.py +3 -0
  606. package/ref-monty/crates/monty/test_cases/type_error__unary_invert_str.py +3 -0
  607. package/ref-monty/crates/monty/test_cases/type_error__unary_minus_str.py +4 -0
  608. package/ref-monty/crates/monty/test_cases/type_error__unary_neg_str.py +3 -0
  609. package/ref-monty/crates/monty/test_cases/type_error__unary_plus_str.py +4 -0
  610. package/ref-monty/crates/monty/test_cases/typing__types.py +24 -0
  611. package/ref-monty/crates/monty/test_cases/unpack__nested.py +48 -0
  612. package/ref-monty/crates/monty/test_cases/unpack__non_sequence.py +9 -0
  613. package/ref-monty/crates/monty/test_cases/unpack__not_enough.py +9 -0
  614. package/ref-monty/crates/monty/test_cases/unpack__ops.py +153 -0
  615. package/ref-monty/crates/monty/test_cases/unpack__star_not_enough.py +9 -0
  616. package/ref-monty/crates/monty/test_cases/unpack__too_many.py +9 -0
  617. package/ref-monty/crates/monty/test_cases/version__cpython.py +4 -0
  618. package/ref-monty/crates/monty/test_cases/walrus__all.py +178 -0
  619. package/ref-monty/crates/monty/test_cases/while__all.py +206 -0
  620. package/ref-monty/crates/monty/tests/asyncio.rs +764 -0
  621. package/ref-monty/crates/monty/tests/binary_serde.rs +185 -0
  622. package/ref-monty/crates/monty/tests/bytecode_limits.rs +248 -0
  623. package/ref-monty/crates/monty/tests/datatest_runner.rs +2029 -0
  624. package/ref-monty/crates/monty/tests/inputs.rs +420 -0
  625. package/ref-monty/crates/monty/tests/json_serde.rs +250 -0
  626. package/ref-monty/crates/monty/tests/main.rs +71 -0
  627. package/ref-monty/crates/monty/tests/math_module.rs +114 -0
  628. package/ref-monty/crates/monty/tests/name_lookup.rs +482 -0
  629. package/ref-monty/crates/monty/tests/os_tests.rs +459 -0
  630. package/ref-monty/crates/monty/tests/parse_errors.rs +441 -0
  631. package/ref-monty/crates/monty/tests/print_writer.rs +238 -0
  632. package/ref-monty/crates/monty/tests/py_object.rs +121 -0
  633. package/ref-monty/crates/monty/tests/regex.rs +90 -0
  634. package/ref-monty/crates/monty/tests/repl.rs +344 -0
  635. package/ref-monty/crates/monty/tests/resource_limits.rs +1826 -0
  636. package/ref-monty/crates/monty/tests/try_from.rs +167 -0
  637. package/ref-monty/crates/monty-cli/Cargo.toml +25 -0
  638. package/ref-monty/crates/monty-cli/src/main.rs +541 -0
  639. package/ref-monty/crates/monty-js/.cargo/config.toml +2 -0
  640. package/ref-monty/crates/monty-js/.prettierignore +8 -0
  641. package/ref-monty/crates/monty-js/Cargo.toml +32 -0
  642. package/ref-monty/crates/monty-js/README.md +207 -0
  643. package/ref-monty/crates/monty-js/__test__/async.spec.ts +350 -0
  644. package/ref-monty/crates/monty-js/__test__/basic.spec.ts +114 -0
  645. package/ref-monty/crates/monty-js/__test__/exceptions.spec.ts +427 -0
  646. package/ref-monty/crates/monty-js/__test__/external.spec.ts +354 -0
  647. package/ref-monty/crates/monty-js/__test__/inputs.spec.ts +143 -0
  648. package/ref-monty/crates/monty-js/__test__/limits.spec.ts +162 -0
  649. package/ref-monty/crates/monty-js/__test__/package.json +3 -0
  650. package/ref-monty/crates/monty-js/__test__/print.spec.ts +229 -0
  651. package/ref-monty/crates/monty-js/__test__/repl.spec.ts +34 -0
  652. package/ref-monty/crates/monty-js/__test__/serialize.spec.ts +205 -0
  653. package/ref-monty/crates/monty-js/__test__/start.spec.ts +443 -0
  654. package/ref-monty/crates/monty-js/__test__/type_check.spec.ts +147 -0
  655. package/ref-monty/crates/monty-js/__test__/types.spec.ts +319 -0
  656. package/ref-monty/crates/monty-js/build.rs +61 -0
  657. package/ref-monty/crates/monty-js/index-header.d.ts +3 -0
  658. package/ref-monty/crates/monty-js/package-lock.json +4694 -0
  659. package/ref-monty/crates/monty-js/package.json +100 -0
  660. package/ref-monty/crates/monty-js/scripts/smoke-test.sh +69 -0
  661. package/ref-monty/crates/monty-js/smoke-test/package.json +17 -0
  662. package/ref-monty/crates/monty-js/smoke-test/test.ts +171 -0
  663. package/ref-monty/crates/monty-js/smoke-test/tsconfig.json +11 -0
  664. package/ref-monty/crates/monty-js/src/convert.rs +648 -0
  665. package/ref-monty/crates/monty-js/src/exceptions.rs +293 -0
  666. package/ref-monty/crates/monty-js/src/lib.rs +41 -0
  667. package/ref-monty/crates/monty-js/src/limits.rs +53 -0
  668. package/ref-monty/crates/monty-js/src/monty_cls.rs +1407 -0
  669. package/ref-monty/crates/monty-js/tsconfig.json +17 -0
  670. package/ref-monty/crates/monty-js/wrapper.ts +701 -0
  671. package/ref-monty/crates/monty-python/Cargo.toml +38 -0
  672. package/ref-monty/crates/monty-python/README.md +134 -0
  673. package/ref-monty/crates/monty-python/build.rs +4 -0
  674. package/ref-monty/crates/monty-python/example.py +40 -0
  675. package/ref-monty/crates/monty-python/exercise.py +46 -0
  676. package/ref-monty/crates/monty-python/pyproject.toml +57 -0
  677. package/ref-monty/crates/monty-python/python/pydantic_monty/__init__.py +281 -0
  678. package/ref-monty/crates/monty-python/python/pydantic_monty/_monty.pyi +677 -0
  679. package/ref-monty/crates/monty-python/python/pydantic_monty/os_access.py +933 -0
  680. package/ref-monty/crates/monty-python/python/pydantic_monty/py.typed +0 -0
  681. package/ref-monty/crates/monty-python/src/convert.rs +273 -0
  682. package/ref-monty/crates/monty-python/src/dataclass.rs +461 -0
  683. package/ref-monty/crates/monty-python/src/exceptions.rs +557 -0
  684. package/ref-monty/crates/monty-python/src/external.rs +165 -0
  685. package/ref-monty/crates/monty-python/src/lib.rs +77 -0
  686. package/ref-monty/crates/monty-python/src/limits.rs +142 -0
  687. package/ref-monty/crates/monty-python/src/monty_cls.rs +1650 -0
  688. package/ref-monty/crates/monty-python/src/repl.rs +470 -0
  689. package/ref-monty/crates/monty-python/src/serialization.rs +761 -0
  690. package/ref-monty/crates/monty-python/tests/test_async.py +1201 -0
  691. package/ref-monty/crates/monty-python/tests/test_basic.py +66 -0
  692. package/ref-monty/crates/monty-python/tests/test_dataclasses.py +971 -0
  693. package/ref-monty/crates/monty-python/tests/test_exceptions.py +361 -0
  694. package/ref-monty/crates/monty-python/tests/test_external.py +367 -0
  695. package/ref-monty/crates/monty-python/tests/test_inputs.py +126 -0
  696. package/ref-monty/crates/monty-python/tests/test_limits.py +257 -0
  697. package/ref-monty/crates/monty-python/tests/test_os_access.py +1286 -0
  698. package/ref-monty/crates/monty-python/tests/test_os_access_compat.py +731 -0
  699. package/ref-monty/crates/monty-python/tests/test_os_access_raw.py +483 -0
  700. package/ref-monty/crates/monty-python/tests/test_os_calls.py +819 -0
  701. package/ref-monty/crates/monty-python/tests/test_print.py +208 -0
  702. package/ref-monty/crates/monty-python/tests/test_re.py +170 -0
  703. package/ref-monty/crates/monty-python/tests/test_readme_examples.py +20 -0
  704. package/ref-monty/crates/monty-python/tests/test_repl.py +749 -0
  705. package/ref-monty/crates/monty-python/tests/test_serialize.py +284 -0
  706. package/ref-monty/crates/monty-python/tests/test_start.py +346 -0
  707. package/ref-monty/crates/monty-python/tests/test_threading.py +163 -0
  708. package/ref-monty/crates/monty-python/tests/test_type_check.py +344 -0
  709. package/ref-monty/crates/monty-python/tests/test_types.py +553 -0
  710. package/ref-monty/crates/monty-type-checking/Cargo.toml +32 -0
  711. package/ref-monty/crates/monty-type-checking/src/db.rs +116 -0
  712. package/ref-monty/crates/monty-type-checking/src/lib.rs +4 -0
  713. package/ref-monty/crates/monty-type-checking/src/type_check.rs +280 -0
  714. package/ref-monty/crates/monty-type-checking/tests/bad_types.py +109 -0
  715. package/ref-monty/crates/monty-type-checking/tests/bad_types_output.txt +21 -0
  716. package/ref-monty/crates/monty-type-checking/tests/good_types.py +475 -0
  717. package/ref-monty/crates/monty-type-checking/tests/main.rs +205 -0
  718. package/ref-monty/crates/monty-type-checking/tests/reveal_types.py +56 -0
  719. package/ref-monty/crates/monty-type-checking/tests/reveal_types_output.txt +41 -0
  720. package/ref-monty/crates/monty-typeshed/Cargo.toml +29 -0
  721. package/ref-monty/crates/monty-typeshed/README.md +11 -0
  722. package/ref-monty/crates/monty-typeshed/build.rs +101 -0
  723. package/ref-monty/crates/monty-typeshed/custom/README.md +1 -0
  724. package/ref-monty/crates/monty-typeshed/custom/asyncio.pyi +138 -0
  725. package/ref-monty/crates/monty-typeshed/custom/os.pyi +87 -0
  726. package/ref-monty/crates/monty-typeshed/custom/sys.pyi +33 -0
  727. package/ref-monty/crates/monty-typeshed/src/lib.rs +56 -0
  728. package/ref-monty/crates/monty-typeshed/update.py +321 -0
  729. package/ref-monty/crates/monty-typeshed/vendor/typeshed/source_commit.txt +1 -0
  730. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/VERSIONS +20 -0
  731. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi +105 -0
  732. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi +394 -0
  733. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi +138 -0
  734. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi +1434 -0
  735. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi +527 -0
  736. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/abc.pyi +2 -0
  737. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/dataclasses.pyi +502 -0
  738. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/enum.pyi +376 -0
  739. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/math.pyi +149 -0
  740. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/os.pyi +87 -0
  741. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/__init__.pyi +395 -0
  742. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/types.pyi +8 -0
  743. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/re.pyi +337 -0
  744. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/sys.pyi +33 -0
  745. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/types.pyi +741 -0
  746. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing.pyi +1217 -0
  747. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing_extensions.pyi +716 -0
  748. package/ref-monty/docs/usage-guide.md +117 -0
  749. package/ref-monty/examples/README.md +3 -0
  750. package/ref-monty/examples/expense_analysis/README.md +3 -0
  751. package/ref-monty/examples/expense_analysis/data.py +124 -0
  752. package/ref-monty/examples/expense_analysis/main.py +115 -0
  753. package/ref-monty/examples/sql_playground/README.md +20 -0
  754. package/ref-monty/examples/sql_playground/external_functions.py +129 -0
  755. package/ref-monty/examples/sql_playground/main.py +81 -0
  756. package/ref-monty/examples/sql_playground/sandbox_code.py +82 -0
  757. package/ref-monty/examples/sql_playground/type_stubs.pyi +14 -0
  758. package/ref-monty/examples/web_scraper/README.md +15 -0
  759. package/ref-monty/examples/web_scraper/browser.py +56 -0
  760. package/ref-monty/examples/web_scraper/example_code.py +59 -0
  761. package/ref-monty/examples/web_scraper/external_functions.py +324 -0
  762. package/ref-monty/examples/web_scraper/main.py +193 -0
  763. package/ref-monty/examples/web_scraper/sub_agent.py +79 -0
  764. package/ref-monty/monty-npm.md +235 -0
  765. package/ref-monty/pyproject.toml +162 -0
  766. package/ref-monty/scripts/check_imports.py +91 -0
  767. package/ref-monty/scripts/codecov_diff.py +412 -0
  768. package/ref-monty/scripts/complete_tests.py +146 -0
  769. package/ref-monty/scripts/flamegraph_to_text.py +208 -0
  770. package/ref-monty/scripts/iter_test_methods.py +540 -0
  771. package/ref-monty/scripts/run_traceback.py +180 -0
  772. package/ref-monty/scripts/startup_performance.py +130 -0
  773. package/ref-monty/uv.lock +1779 -0
  774. package/temp_resend_cli/repo/.github/scripts/pr-title-check.js +34 -0
  775. package/temp_resend_cli/repo/.github/workflows/ci.yml +67 -0
  776. package/temp_resend_cli/repo/.github/workflows/post-release.yml +51 -0
  777. package/temp_resend_cli/repo/.github/workflows/pr-title-check.yml +13 -0
  778. package/temp_resend_cli/repo/.github/workflows/release.yml +175 -0
  779. package/temp_resend_cli/repo/.github/workflows/test-install-unix.yml +34 -0
  780. package/temp_resend_cli/repo/.github/workflows/test-install-windows.yml +48 -0
  781. package/temp_resend_cli/repo/CHANGELOG.md +31 -0
  782. package/temp_resend_cli/repo/LICENSE +21 -0
  783. package/temp_resend_cli/repo/README.md +450 -0
  784. package/temp_resend_cli/repo/biome.json +36 -0
  785. package/temp_resend_cli/repo/install.ps1 +141 -0
  786. package/temp_resend_cli/repo/install.sh +301 -0
  787. package/temp_resend_cli/repo/package.json +61 -0
  788. package/temp_resend_cli/repo/pnpm-lock.yaml +2439 -0
  789. package/temp_resend_cli/repo/renovate.json +4 -0
  790. package/temp_resend_cli/repo/src/cli.ts +98 -0
  791. package/temp_resend_cli/repo/src/commands/api-keys/create.ts +114 -0
  792. package/temp_resend_cli/repo/src/commands/api-keys/delete.ts +47 -0
  793. package/temp_resend_cli/repo/src/commands/api-keys/index.ts +26 -0
  794. package/temp_resend_cli/repo/src/commands/api-keys/list.ts +35 -0
  795. package/temp_resend_cli/repo/src/commands/api-keys/utils.ts +8 -0
  796. package/temp_resend_cli/repo/src/commands/auth/index.ts +20 -0
  797. package/temp_resend_cli/repo/src/commands/auth/login.ts +234 -0
  798. package/temp_resend_cli/repo/src/commands/auth/logout.ts +105 -0
  799. package/temp_resend_cli/repo/src/commands/broadcasts/create.ts +196 -0
  800. package/temp_resend_cli/repo/src/commands/broadcasts/delete.ts +46 -0
  801. package/temp_resend_cli/repo/src/commands/broadcasts/get.ts +59 -0
  802. package/temp_resend_cli/repo/src/commands/broadcasts/index.ts +43 -0
  803. package/temp_resend_cli/repo/src/commands/broadcasts/list.ts +60 -0
  804. package/temp_resend_cli/repo/src/commands/broadcasts/send.ts +56 -0
  805. package/temp_resend_cli/repo/src/commands/broadcasts/update.ts +95 -0
  806. package/temp_resend_cli/repo/src/commands/broadcasts/utils.ts +35 -0
  807. package/temp_resend_cli/repo/src/commands/contact-properties/create.ts +118 -0
  808. package/temp_resend_cli/repo/src/commands/contact-properties/delete.ts +48 -0
  809. package/temp_resend_cli/repo/src/commands/contact-properties/get.ts +46 -0
  810. package/temp_resend_cli/repo/src/commands/contact-properties/index.ts +48 -0
  811. package/temp_resend_cli/repo/src/commands/contact-properties/list.ts +68 -0
  812. package/temp_resend_cli/repo/src/commands/contact-properties/update.ts +88 -0
  813. package/temp_resend_cli/repo/src/commands/contact-properties/utils.ts +17 -0
  814. package/temp_resend_cli/repo/src/commands/contacts/add-segment.ts +78 -0
  815. package/temp_resend_cli/repo/src/commands/contacts/create.ts +122 -0
  816. package/temp_resend_cli/repo/src/commands/contacts/delete.ts +49 -0
  817. package/temp_resend_cli/repo/src/commands/contacts/get.ts +53 -0
  818. package/temp_resend_cli/repo/src/commands/contacts/index.ts +58 -0
  819. package/temp_resend_cli/repo/src/commands/contacts/list.ts +57 -0
  820. package/temp_resend_cli/repo/src/commands/contacts/remove-segment.ts +48 -0
  821. package/temp_resend_cli/repo/src/commands/contacts/segments.ts +39 -0
  822. package/temp_resend_cli/repo/src/commands/contacts/topics.ts +45 -0
  823. package/temp_resend_cli/repo/src/commands/contacts/update-topics.ts +90 -0
  824. package/temp_resend_cli/repo/src/commands/contacts/update.ts +77 -0
  825. package/temp_resend_cli/repo/src/commands/contacts/utils.ts +119 -0
  826. package/temp_resend_cli/repo/src/commands/doctor.ts +216 -0
  827. package/temp_resend_cli/repo/src/commands/domains/create.ts +83 -0
  828. package/temp_resend_cli/repo/src/commands/domains/delete.ts +42 -0
  829. package/temp_resend_cli/repo/src/commands/domains/get.ts +47 -0
  830. package/temp_resend_cli/repo/src/commands/domains/index.ts +35 -0
  831. package/temp_resend_cli/repo/src/commands/domains/list.ts +53 -0
  832. package/temp_resend_cli/repo/src/commands/domains/update.ts +75 -0
  833. package/temp_resend_cli/repo/src/commands/domains/utils.ts +44 -0
  834. package/temp_resend_cli/repo/src/commands/domains/verify.ts +38 -0
  835. package/temp_resend_cli/repo/src/commands/emails/batch.ts +140 -0
  836. package/temp_resend_cli/repo/src/commands/emails/get.ts +44 -0
  837. package/temp_resend_cli/repo/src/commands/emails/index.ts +30 -0
  838. package/temp_resend_cli/repo/src/commands/emails/list.ts +84 -0
  839. package/temp_resend_cli/repo/src/commands/emails/receiving/attachment.ts +55 -0
  840. package/temp_resend_cli/repo/src/commands/emails/receiving/attachments.ts +68 -0
  841. package/temp_resend_cli/repo/src/commands/emails/receiving/get.ts +58 -0
  842. package/temp_resend_cli/repo/src/commands/emails/receiving/index.ts +28 -0
  843. package/temp_resend_cli/repo/src/commands/emails/receiving/list.ts +59 -0
  844. package/temp_resend_cli/repo/src/commands/emails/receiving/utils.ts +38 -0
  845. package/temp_resend_cli/repo/src/commands/emails/send.ts +189 -0
  846. package/temp_resend_cli/repo/src/commands/open.ts +27 -0
  847. package/temp_resend_cli/repo/src/commands/segments/create.ts +50 -0
  848. package/temp_resend_cli/repo/src/commands/segments/delete.ts +47 -0
  849. package/temp_resend_cli/repo/src/commands/segments/get.ts +38 -0
  850. package/temp_resend_cli/repo/src/commands/segments/index.ts +36 -0
  851. package/temp_resend_cli/repo/src/commands/segments/list.ts +58 -0
  852. package/temp_resend_cli/repo/src/commands/segments/utils.ts +7 -0
  853. package/temp_resend_cli/repo/src/commands/teams/index.ts +10 -0
  854. package/temp_resend_cli/repo/src/commands/teams/list.ts +35 -0
  855. package/temp_resend_cli/repo/src/commands/teams/remove.ts +86 -0
  856. package/temp_resend_cli/repo/src/commands/teams/switch.ts +76 -0
  857. package/temp_resend_cli/repo/src/commands/topics/create.ts +73 -0
  858. package/temp_resend_cli/repo/src/commands/topics/delete.ts +47 -0
  859. package/temp_resend_cli/repo/src/commands/topics/get.ts +42 -0
  860. package/temp_resend_cli/repo/src/commands/topics/index.ts +42 -0
  861. package/temp_resend_cli/repo/src/commands/topics/list.ts +34 -0
  862. package/temp_resend_cli/repo/src/commands/topics/update.ts +59 -0
  863. package/temp_resend_cli/repo/src/commands/topics/utils.ts +16 -0
  864. package/temp_resend_cli/repo/src/commands/webhooks/create.ts +128 -0
  865. package/temp_resend_cli/repo/src/commands/webhooks/delete.ts +49 -0
  866. package/temp_resend_cli/repo/src/commands/webhooks/get.ts +42 -0
  867. package/temp_resend_cli/repo/src/commands/webhooks/index.ts +42 -0
  868. package/temp_resend_cli/repo/src/commands/webhooks/list.ts +55 -0
  869. package/temp_resend_cli/repo/src/commands/webhooks/listen.ts +379 -0
  870. package/temp_resend_cli/repo/src/commands/webhooks/update.ts +83 -0
  871. package/temp_resend_cli/repo/src/commands/webhooks/utils.ts +36 -0
  872. package/temp_resend_cli/repo/src/commands/whoami.ts +71 -0
  873. package/temp_resend_cli/repo/src/lib/actions.ts +157 -0
  874. package/temp_resend_cli/repo/src/lib/client.ts +37 -0
  875. package/temp_resend_cli/repo/src/lib/config.ts +217 -0
  876. package/temp_resend_cli/repo/src/lib/files.ts +15 -0
  877. package/temp_resend_cli/repo/src/lib/help-text.ts +38 -0
  878. package/temp_resend_cli/repo/src/lib/output.ts +56 -0
  879. package/temp_resend_cli/repo/src/lib/pagination.ts +36 -0
  880. package/temp_resend_cli/repo/src/lib/prompts.ts +149 -0
  881. package/temp_resend_cli/repo/src/lib/spinner.ts +100 -0
  882. package/temp_resend_cli/repo/src/lib/table.ts +57 -0
  883. package/temp_resend_cli/repo/src/lib/tty.ts +28 -0
  884. package/temp_resend_cli/repo/src/lib/update-check.ts +169 -0
  885. package/temp_resend_cli/repo/src/lib/version.ts +4 -0
  886. package/temp_resend_cli/repo/tests/commands/api-keys/create.test.ts +196 -0
  887. package/temp_resend_cli/repo/tests/commands/api-keys/delete.test.ts +157 -0
  888. package/temp_resend_cli/repo/tests/commands/api-keys/list.test.ts +134 -0
  889. package/temp_resend_cli/repo/tests/commands/auth/login.test.ts +153 -0
  890. package/temp_resend_cli/repo/tests/commands/auth/logout.test.ts +153 -0
  891. package/temp_resend_cli/repo/tests/commands/broadcasts/create.test.ts +454 -0
  892. package/temp_resend_cli/repo/tests/commands/broadcasts/delete.test.ts +183 -0
  893. package/temp_resend_cli/repo/tests/commands/broadcasts/get.test.ts +147 -0
  894. package/temp_resend_cli/repo/tests/commands/broadcasts/list.test.ts +199 -0
  895. package/temp_resend_cli/repo/tests/commands/broadcasts/send.test.ts +162 -0
  896. package/temp_resend_cli/repo/tests/commands/broadcasts/update.test.ts +288 -0
  897. package/temp_resend_cli/repo/tests/commands/contact-properties/create.test.ts +251 -0
  898. package/temp_resend_cli/repo/tests/commands/contact-properties/delete.test.ts +184 -0
  899. package/temp_resend_cli/repo/tests/commands/contact-properties/get.test.ts +145 -0
  900. package/temp_resend_cli/repo/tests/commands/contact-properties/list.test.ts +181 -0
  901. package/temp_resend_cli/repo/tests/commands/contact-properties/update.test.ts +217 -0
  902. package/temp_resend_cli/repo/tests/commands/contacts/add-segment.test.ts +189 -0
  903. package/temp_resend_cli/repo/tests/commands/contacts/create.test.ts +271 -0
  904. package/temp_resend_cli/repo/tests/commands/contacts/delete.test.ts +193 -0
  905. package/temp_resend_cli/repo/tests/commands/contacts/get.test.ts +149 -0
  906. package/temp_resend_cli/repo/tests/commands/contacts/list.test.ts +176 -0
  907. package/temp_resend_cli/repo/tests/commands/contacts/remove-segment.test.ts +167 -0
  908. package/temp_resend_cli/repo/tests/commands/contacts/segments.test.ts +168 -0
  909. package/temp_resend_cli/repo/tests/commands/contacts/topics.test.ts +164 -0
  910. package/temp_resend_cli/repo/tests/commands/contacts/update-topics.test.ts +248 -0
  911. package/temp_resend_cli/repo/tests/commands/contacts/update.test.ts +206 -0
  912. package/temp_resend_cli/repo/tests/commands/doctor.test.ts +164 -0
  913. package/temp_resend_cli/repo/tests/commands/domains/create.test.ts +193 -0
  914. package/temp_resend_cli/repo/tests/commands/domains/delete.test.ts +157 -0
  915. package/temp_resend_cli/repo/tests/commands/domains/get.test.ts +138 -0
  916. package/temp_resend_cli/repo/tests/commands/domains/list.test.ts +165 -0
  917. package/temp_resend_cli/repo/tests/commands/domains/update.test.ts +224 -0
  918. package/temp_resend_cli/repo/tests/commands/domains/verify.test.ts +118 -0
  919. package/temp_resend_cli/repo/tests/commands/emails/batch.test.ts +324 -0
  920. package/temp_resend_cli/repo/tests/commands/emails/get.test.ts +132 -0
  921. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachment.test.ts +141 -0
  922. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachments.test.ts +169 -0
  923. package/temp_resend_cli/repo/tests/commands/emails/receiving/get.test.ts +141 -0
  924. package/temp_resend_cli/repo/tests/commands/emails/receiving/list.test.ts +182 -0
  925. package/temp_resend_cli/repo/tests/commands/emails/send.test.ts +312 -0
  926. package/temp_resend_cli/repo/tests/commands/segments/create.test.ts +164 -0
  927. package/temp_resend_cli/repo/tests/commands/segments/delete.test.ts +183 -0
  928. package/temp_resend_cli/repo/tests/commands/segments/get.test.ts +138 -0
  929. package/temp_resend_cli/repo/tests/commands/segments/list.test.ts +174 -0
  930. package/temp_resend_cli/repo/tests/commands/teams/list.test.ts +62 -0
  931. package/temp_resend_cli/repo/tests/commands/teams/remove.test.ts +110 -0
  932. package/temp_resend_cli/repo/tests/commands/teams/switch.test.ts +103 -0
  933. package/temp_resend_cli/repo/tests/commands/topics/create.test.ts +192 -0
  934. package/temp_resend_cli/repo/tests/commands/topics/delete.test.ts +157 -0
  935. package/temp_resend_cli/repo/tests/commands/topics/get.test.ts +126 -0
  936. package/temp_resend_cli/repo/tests/commands/topics/list.test.ts +125 -0
  937. package/temp_resend_cli/repo/tests/commands/topics/update.test.ts +178 -0
  938. package/temp_resend_cli/repo/tests/commands/webhooks/create.test.ts +225 -0
  939. package/temp_resend_cli/repo/tests/commands/webhooks/delete.test.ts +157 -0
  940. package/temp_resend_cli/repo/tests/commands/webhooks/get.test.ts +126 -0
  941. package/temp_resend_cli/repo/tests/commands/webhooks/list.test.ts +178 -0
  942. package/temp_resend_cli/repo/tests/commands/webhooks/update.test.ts +207 -0
  943. package/temp_resend_cli/repo/tests/commands/whoami.test.ts +98 -0
  944. package/temp_resend_cli/repo/tests/e2e/smoke.test.ts +93 -0
  945. package/temp_resend_cli/repo/tests/helpers.ts +86 -0
  946. package/temp_resend_cli/repo/tests/lib/client.test.ts +71 -0
  947. package/temp_resend_cli/repo/tests/lib/config.test.ts +451 -0
  948. package/temp_resend_cli/repo/tests/lib/files.test.ts +73 -0
  949. package/temp_resend_cli/repo/tests/lib/help-text.test.ts +97 -0
  950. package/temp_resend_cli/repo/tests/lib/output.test.ts +136 -0
  951. package/temp_resend_cli/repo/tests/lib/prompts.test.ts +185 -0
  952. package/temp_resend_cli/repo/tests/lib/spinner.test.ts +166 -0
  953. package/temp_resend_cli/repo/tests/lib/table.test.ts +63 -0
  954. package/temp_resend_cli/repo/tests/lib/tty.test.ts +89 -0
  955. package/temp_resend_cli/repo/tests/lib/update-check.test.ts +179 -0
  956. package/temp_resend_cli/repo/tsconfig.json +14 -0
  957. package/temp_resend_cli/repo/vitest.config.e2e.ts +8 -0
  958. package/temp_resend_cli/repo/vitest.config.ts +10 -0
  959. package/tests/test-mcp-browser-use-smoke.sh +28 -56
  960. package/tests/test-monty-smoke.sh +32 -0
  961. package/tests/test-resend-smoke.sh +36 -0
@@ -0,0 +1,1073 @@
1
+ use std::{
2
+ cell::Cell,
3
+ collections::hash_map::DefaultHasher,
4
+ hash::{Hash, Hasher},
5
+ mem::size_of,
6
+ vec,
7
+ };
8
+
9
+ use smallvec::SmallVec;
10
+
11
+ // Re-export items moved to `heap_traits` so that `crate::heap::HeapGuard` etc. continue
12
+ // to resolve (used by the `defer_drop!` macros and throughout the codebase).
13
+ pub(crate) use crate::heap_data::HeapData;
14
+ pub(crate) use crate::heap_traits::{ContainsHeap, DropWithHeap, HeapGuard, ImmutableHeapGuard};
15
+ use crate::{
16
+ args::ArgValues,
17
+ asyncio::GatherItem,
18
+ bytecode::{CallResult, VM},
19
+ exception_private::{ExcType, RunResult},
20
+ heap_data::HeapDataMut,
21
+ intern::Interns,
22
+ resource::{ResourceError, ResourceTracker, check_mult_size, check_repeat_size},
23
+ types::{List, LongInt, PyTrait, Tuple, allocate_tuple},
24
+ value::{EitherStr, Value},
25
+ };
26
+
27
+ /// Unique identifier for values stored inside the heap arena.
28
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
29
+ pub struct HeapId(usize);
30
+
31
+ impl HeapId {
32
+ /// Returns the raw index value.
33
+ #[inline]
34
+ pub fn index(self) -> usize {
35
+ self.0
36
+ }
37
+ }
38
+
39
+ /// The empty tuple is a singleton which is allocated at startup.
40
+ const EMPTY_TUPLE_ID: HeapId = HeapId(0);
41
+
42
+ /// Hash caching state stored alongside each heap entry.
43
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
44
+ enum HashState {
45
+ /// Hash has not yet been computed but the value might be hashable.
46
+ Unknown,
47
+ /// Cached hash value for immutable types that have been hashed at least once.
48
+ Cached(u64),
49
+ /// Value is unhashable (mutable types or tuples containing unhashables).
50
+ Unhashable,
51
+ }
52
+
53
+ impl HashState {
54
+ fn for_data(data: &HeapData) -> Self {
55
+ match data {
56
+ // Cells are hashable by identity (like all Python objects without __hash__ override)
57
+ // FrozenSet is immutable and hashable
58
+ // Range is immutable and hashable
59
+ // Slice is immutable and hashable (like in CPython)
60
+ // LongInt is immutable and hashable
61
+ // NamedTuple is immutable and hashable (like Tuple)
62
+ HeapData::Str(_)
63
+ | HeapData::Bytes(_)
64
+ | HeapData::Tuple(_)
65
+ | HeapData::NamedTuple(_)
66
+ | HeapData::FrozenSet(_)
67
+ | HeapData::Cell(_)
68
+ | HeapData::Closure(_)
69
+ | HeapData::FunctionDefaults(_)
70
+ | HeapData::Range(_)
71
+ | HeapData::Slice(_)
72
+ | HeapData::LongInt(_) => Self::Unknown,
73
+ // Dataclass hashability depends on the mutable flag
74
+ HeapData::Dataclass(dc) => {
75
+ if dc.is_frozen() {
76
+ Self::Unknown
77
+ } else {
78
+ Self::Unhashable
79
+ }
80
+ }
81
+ // Path is immutable and hashable
82
+ HeapData::Path(_) => Self::Unknown,
83
+ // ExtFunction is hashable (by identity, like closures)
84
+ HeapData::ExtFunction(_) => Self::Unknown,
85
+ // other types are unhashable
86
+ _ => Self::Unhashable,
87
+ }
88
+ }
89
+ }
90
+
91
+ /// A single entry inside the heap arena, storing refcount, payload, and hash metadata.
92
+ ///
93
+ /// The `hash_state` field tracks whether the heap entry is hashable and, if so,
94
+ /// caches the computed hash. Mutable types (List, Dict) start as `Unhashable` and
95
+ /// will raise TypeError if used as dict keys.
96
+ ///
97
+ /// The `data` field is an Option to support temporary borrowing: when methods like
98
+ /// `with_entry_mut` or `call_attr` need mutable access to both the data and the heap,
99
+ /// they can `.take()` the data out (leaving `None`), pass `&mut Heap` to user code,
100
+ /// then restore the data. This avoids unsafe code while keeping `refcount` accessible
101
+ /// for `inc_ref`/`dec_ref` during the borrow.
102
+ #[derive(Debug, serde::Serialize, serde::Deserialize)]
103
+ pub struct HeapValue {
104
+ refcount: Cell<usize>,
105
+ /// The payload data. Temporarily `None` while borrowed via `with_entry_mut`/`call_attr`.
106
+ data: Option<HeapData>,
107
+ /// Current hashing status / cached hash value
108
+ hash_state: HashState,
109
+ }
110
+
111
+ /// Zero-size token returned by [`Heap::incr_recursion_depth`].
112
+ ///
113
+ /// Represents one level of recursion depth that must be released when the
114
+ /// recursive operation completes. There are two ways to release the token:
115
+ ///
116
+ /// - **`DropWithHeap`** — for `&mut Heap` paths (e.g., `py_eq`). Compatible with
117
+ /// `defer_drop!` and `HeapGuard` for automatic cleanup on all code paths.
118
+ /// - **`DropWithImmutableHeap`** — for `&Heap` paths (e.g., `py_repr_fmt`) where
119
+ /// only shared access is available. Compatible with `defer_drop_immutable_heap!`
120
+ /// and `ImmutableHeapGuard`.
121
+ #[derive(Debug)]
122
+ pub(crate) struct RecursionToken(());
123
+
124
+ impl DropWithHeap for RecursionToken {
125
+ #[inline]
126
+ fn drop_with_heap<H: ContainsHeap>(self, heap: &mut H) {
127
+ heap.heap().decr_recursion_depth();
128
+ }
129
+ }
130
+
131
+ /// Reference-counted arena that backs all heap-only runtime values.
132
+ ///
133
+ /// Uses a free list to reuse slots from freed values, keeping memory usage
134
+ /// constant for long-running loops that repeatedly allocate and free values.
135
+ /// When an value is freed via `dec_ref`, its slot ID is added to the free list.
136
+ /// New allocations pop from the free list when available, otherwise append.
137
+ ///
138
+ /// Generic over `T: ResourceTracker` to support different resource tracking strategies.
139
+ /// When `T = NoLimitTracker` (the default), all resource checks compile away to no-ops.
140
+ ///
141
+ /// Serialization requires `T: Serialize` and `T: Deserialize`. Custom serde implementation
142
+ /// handles the Drop constraint by using `std::mem::take` during serialization.
143
+ #[derive(Debug)]
144
+ pub(crate) struct Heap<T: ResourceTracker> {
145
+ entries: Vec<Option<HeapValue>>,
146
+ /// IDs of freed slots available for reuse. Populated by `dec_ref`, consumed by `allocate`.
147
+ free_list: Vec<HeapId>,
148
+ /// Resource tracker for enforcing limits and scheduling GC.
149
+ tracker: T,
150
+ /// True if reference cycles may exist. Set when a container stores a Ref,
151
+ /// cleared after GC completes. When false, GC can skip mark-sweep entirely.
152
+ may_have_cycles: bool,
153
+ /// Number of GC applicable allocations since the last GC.
154
+ allocations_since_gc: u32,
155
+ /// Current recursion depth — incremented on function calls and data structure traversals.
156
+ ///
157
+ /// Uses `Cell` for interior mutability so that methods with only `&Heap`
158
+ /// (like `py_repr_fmt`) can still increment/decrement the depth counter.
159
+ recursion_depth: Cell<usize>,
160
+ }
161
+
162
+ impl<T: ResourceTracker + serde::Serialize> serde::Serialize for Heap<T> {
163
+ fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
164
+ use serde::ser::SerializeStruct;
165
+ let mut state = serializer.serialize_struct("Heap", 6)?;
166
+ state.serialize_field("entries", &self.entries)?;
167
+ state.serialize_field("free_list", &self.free_list)?;
168
+ state.serialize_field("tracker", &self.tracker)?;
169
+ state.serialize_field("may_have_cycles", &self.may_have_cycles)?;
170
+ state.serialize_field("allocations_since_gc", &self.allocations_since_gc)?;
171
+ state.end()
172
+ }
173
+ }
174
+
175
+ impl<'de, T: ResourceTracker + serde::Deserialize<'de>> serde::Deserialize<'de> for Heap<T> {
176
+ fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
177
+ #[derive(serde::Deserialize)]
178
+ struct HeapFields<T> {
179
+ entries: Vec<Option<HeapValue>>,
180
+ free_list: Vec<HeapId>,
181
+ tracker: T,
182
+ may_have_cycles: bool,
183
+ allocations_since_gc: u32,
184
+ }
185
+ let fields = HeapFields::<T>::deserialize(deserializer)?;
186
+ Ok(Self {
187
+ entries: fields.entries,
188
+ free_list: fields.free_list,
189
+ tracker: fields.tracker,
190
+ may_have_cycles: fields.may_have_cycles,
191
+ allocations_since_gc: fields.allocations_since_gc,
192
+ recursion_depth: Cell::new(0),
193
+ })
194
+ }
195
+ }
196
+
197
+ macro_rules! take_data {
198
+ ($self:ident, $id:expr, $func_name:literal) => {
199
+ $self
200
+ .entries
201
+ .get_mut($id.index())
202
+ .expect(concat!("Heap::", $func_name, ": slot missing"))
203
+ .as_mut()
204
+ .expect(concat!("Heap::", $func_name, ": object already freed"))
205
+ .data
206
+ .take()
207
+ .expect(concat!("Heap::", $func_name, ": data already borrowed"))
208
+ };
209
+ }
210
+
211
+ macro_rules! restore_data {
212
+ ($self:ident, $id:expr, $new_data:expr, $func_name:literal) => {{
213
+ let entry = $self
214
+ .entries
215
+ .get_mut($id.index())
216
+ .expect(concat!("Heap::", $func_name, ": slot missing"))
217
+ .as_mut()
218
+ .expect(concat!("Heap::", $func_name, ": object already freed"));
219
+ entry.data = Some($new_data);
220
+ }};
221
+ }
222
+
223
+ /// GC interval - run GC every 100,000 applicable allocations.
224
+ ///
225
+ /// This is intentionally infrequent to minimize overhead while still
226
+ /// eventually collecting reference cycles.
227
+ const GC_INTERVAL: u32 = 100_000;
228
+
229
+ impl<T: ResourceTracker> Heap<T> {
230
+ /// Creates a new heap with the given resource tracker.
231
+ ///
232
+ /// Use this to create heaps with custom resource limits or GC scheduling.
233
+ pub fn new(capacity: usize, tracker: T) -> Self {
234
+ let mut this = Self {
235
+ entries: Vec::with_capacity(capacity),
236
+ free_list: Vec::new(),
237
+ tracker,
238
+ may_have_cycles: false,
239
+ allocations_since_gc: 0,
240
+ recursion_depth: Cell::new(0),
241
+ };
242
+ // TBC: should the empty tuple contribute to the resource limits?
243
+ // If not, can just place it in `entries` directly without going through `allocate()`.
244
+ let empty_tuple = this
245
+ .allocate(HeapData::Tuple(Tuple::default()))
246
+ .expect("Failed to allocate empty tuple singleton");
247
+ debug_assert_eq!(empty_tuple, EMPTY_TUPLE_ID);
248
+ this
249
+ }
250
+
251
+ /// Returns a reference to the resource tracker.
252
+ pub fn tracker(&self) -> &T {
253
+ &self.tracker
254
+ }
255
+
256
+ /// Returns a mutable reference to the resource tracker.
257
+ pub fn tracker_mut(&mut self) -> &mut T {
258
+ &mut self.tracker
259
+ }
260
+
261
+ /// Checks whether the configured time limit has been exceeded.
262
+ ///
263
+ /// Delegates to the resource tracker's `check_time()`. For `NoLimitTracker`,
264
+ /// this is inlined as a no-op with zero runtime cost. For `LimitTracker`,
265
+ /// it compares elapsed time against the configured `max_duration_secs`.
266
+ ///
267
+ /// Call this inside Rust-side loops (builtins, sort, iterator collection)
268
+ /// that execute within a single bytecode instruction and would otherwise
269
+ /// bypass the VM's per-instruction timeout check.
270
+ #[inline]
271
+ pub fn check_time(&self) -> Result<(), ResourceError> {
272
+ self.tracker.check_time()
273
+ }
274
+
275
+ /// Increments the recursion depth and checks the limit via the `ResourceTracker`.
276
+ ///
277
+ /// Returns `Ok(RecursionToken)` if within limits. The caller must ensure the
278
+ /// token is released on all code paths — either via `defer_drop!`/`HeapGuard`
279
+ /// (for `&mut Heap` contexts) or via `RecursionToken::release()` (for `&Heap` contexts).
280
+ ///
281
+ /// Returns `Err(ResourceError::Recursion)` if the limit would be exceeded.
282
+ #[inline]
283
+ pub fn incr_recursion_depth(&self) -> Result<RecursionToken, ResourceError> {
284
+ let depth = self.recursion_depth.get();
285
+ self.tracker.check_recursion_depth(depth)?;
286
+ self.recursion_depth.set(depth + 1);
287
+ Ok(RecursionToken(()))
288
+ }
289
+
290
+ /// Increments the recursion depth, returning `Some(RecursionToken)` if within
291
+ /// limits, or `None` if the limit is exceeded.
292
+ ///
293
+ /// Use this in repr-like contexts where exceeding the limit should produce
294
+ /// truncated output (e.g., `[...]`) rather than an error.
295
+ #[inline]
296
+ pub fn incr_recursion_depth_for_repr(&self) -> Option<RecursionToken> {
297
+ self.incr_recursion_depth().ok()
298
+ }
299
+
300
+ /// Decrements the recursion depth.
301
+ ///
302
+ /// Called internally by `RecursionToken` — prefer releasing the token
303
+ /// rather than calling this directly.
304
+ #[inline]
305
+ pub(crate) fn decr_recursion_depth(&self) {
306
+ let depth = self.recursion_depth.get();
307
+ debug_assert!(depth > 0, "decr_recursion_depth called when depth is 0");
308
+ self.recursion_depth.set(depth - 1);
309
+ }
310
+
311
+ /// Returns the current recursion depth.
312
+ ///
313
+ /// Used during async task switching to compute a task's depth contribution
314
+ /// before adjusting the global counter.
315
+ pub(crate) fn get_recursion_depth(&self) -> usize {
316
+ self.recursion_depth.get()
317
+ }
318
+
319
+ /// Sets the recursion depth to an explicit value.
320
+ ///
321
+ /// Used after deserialization to restore the recursion depth to match
322
+ /// the number of active (non-global) namespace frames that were serialized.
323
+ /// Also used during async task switching to subtract/add a task's depth
324
+ /// contribution when switching away from/to that task.
325
+ pub(crate) fn set_recursion_depth(&self, depth: usize) {
326
+ self.recursion_depth.set(depth);
327
+ }
328
+
329
+ /// Number of entries in the heap
330
+ pub fn size(&self) -> usize {
331
+ self.entries.len()
332
+ }
333
+
334
+ /// Marks that a reference cycle may exist in the heap.
335
+ ///
336
+ /// Call this when a container (list, dict, tuple, etc.) stores a reference
337
+ /// to another heap object. This enables the GC to skip mark-sweep entirely
338
+ /// when no cycles are possible.
339
+ #[inline]
340
+ pub fn mark_potential_cycle(&mut self) {
341
+ self.may_have_cycles = true;
342
+ }
343
+
344
+ /// Returns the number of GC-tracked allocations since the last garbage collection.
345
+ ///
346
+ /// This counter increments for each allocation of a GC-tracked type (List, Dict, etc.)
347
+ /// and resets to 0 when `collect_garbage` runs. Useful for testing GC behavior.
348
+ #[cfg(feature = "ref-count-return")]
349
+ pub fn get_allocations_since_gc(&self) -> u32 {
350
+ self.allocations_since_gc
351
+ }
352
+
353
+ /// Allocates a new heap entry.
354
+ ///
355
+ /// Returns `Err(ResourceError)` if allocation would exceed configured limits.
356
+ /// Use this when you need to handle resource limit errors gracefully.
357
+ ///
358
+ /// Only GC-tracked types (containers that can hold references) count toward the
359
+ /// GC allocation threshold. Leaf types like strings don't trigger GC.
360
+ ///
361
+ /// When allocating a container that contains heap references, marks potential
362
+ /// cycles to enable garbage collection.
363
+ pub fn allocate(&mut self, data: HeapData) -> Result<HeapId, ResourceError> {
364
+ self.tracker.on_allocate(|| data.py_estimate_size())?;
365
+ if data.is_gc_tracked() {
366
+ self.allocations_since_gc = self.allocations_since_gc.wrapping_add(1);
367
+ // Mark potential cycles if this container has heap references.
368
+ // This is essential for types like Dict where setitem doesn't call
369
+ // mark_potential_cycle() - the allocation is the only place to detect refs.
370
+ if data.has_refs() {
371
+ self.may_have_cycles = true;
372
+ }
373
+ }
374
+
375
+ let hash_state = HashState::for_data(&data);
376
+ let new_entry = HeapValue {
377
+ refcount: Cell::new(1),
378
+ data: Some(data),
379
+ hash_state,
380
+ };
381
+
382
+ let id = if let Some(id) = self.free_list.pop() {
383
+ // Reuse a freed slot
384
+ self.entries[id.index()] = Some(new_entry);
385
+ id
386
+ } else {
387
+ // No free slots, append new entry
388
+ let id = self.entries.len();
389
+ self.entries.push(Some(new_entry));
390
+ HeapId(id)
391
+ };
392
+
393
+ Ok(id)
394
+ }
395
+
396
+ /// Returns the singleton empty tuple.
397
+ ///
398
+ /// In Python, `() is ()` is always `True` because empty tuples are interned.
399
+ /// This method provides the same optimization by returning the same `HeapId`
400
+ /// for all empty tuple allocations.
401
+ ///
402
+ /// The returned `Value` has its reference count incremented, so the caller
403
+ /// owns a reference and must call `dec_ref` when done.
404
+ pub fn get_empty_tuple(&mut self) -> Value {
405
+ // Return existing singleton with incremented refcount
406
+ self.inc_ref(EMPTY_TUPLE_ID);
407
+ Value::Ref(EMPTY_TUPLE_ID)
408
+ }
409
+
410
+ /// Increments the reference count for an existing heap entry.
411
+ ///
412
+ /// # Panics
413
+ /// Panics if the value ID is invalid or the value has already been freed.
414
+ pub fn inc_ref(&self, id: HeapId) {
415
+ let value = self
416
+ .entries
417
+ .get(id.index())
418
+ .expect("Heap::inc_ref: slot missing")
419
+ .as_ref()
420
+ .expect("Heap::inc_ref: object already freed");
421
+ value.refcount.update(|r| r + 1);
422
+ }
423
+
424
+ /// Decrements the reference count and frees the value (plus children) once it hits zero.
425
+ ///
426
+ /// Uses an iterative work stack instead of recursion to avoid Rust stack overflow
427
+ /// when freeing deeply nested containers (e.g., a list nested 10,000 levels deep).
428
+ /// This is analogous to CPython's "trashcan" mechanism for safe deallocation.
429
+ ///
430
+ /// # Panics
431
+ /// Panics if the value ID is invalid or the value has already been freed.
432
+ pub fn dec_ref(&mut self, id: HeapId) {
433
+ let mut current_id = id;
434
+ let mut work_stack = Vec::new();
435
+ loop {
436
+ let slot = self
437
+ .entries
438
+ .get_mut(current_id.index())
439
+ .expect("Heap::dec_ref: slot missing");
440
+ let entry = slot.as_mut().expect("Heap::dec_ref: object already freed");
441
+ if entry.refcount.get() > 1 {
442
+ entry.refcount.update(|r| r - 1);
443
+ } else if let Some(value) = slot.take() {
444
+ // refcount == 1, free the value and add slot to free list for reuse
445
+ self.free_list.push(current_id);
446
+
447
+ // Notify tracker of freed memory
448
+ if let Some(ref data) = value.data {
449
+ self.tracker.on_free(|| data.py_estimate_size());
450
+ }
451
+
452
+ // Collect child IDs and push onto work stack for iterative processing
453
+ if let Some(mut data) = value.data {
454
+ data.py_dec_ref_ids(&mut work_stack);
455
+ drop(data);
456
+ }
457
+ }
458
+
459
+ let Some(next_id) = work_stack.pop() else {
460
+ break;
461
+ };
462
+ current_id = next_id;
463
+ }
464
+ }
465
+
466
+ /// Returns an immutable reference to the heap data stored at the given ID.
467
+ ///
468
+ /// # Panics
469
+ /// Panics if the value ID is invalid, the value has already been freed,
470
+ /// or the data is currently borrowed via `with_entry_mut`/`call_attr`.
471
+ #[must_use]
472
+ pub fn get(&self, id: HeapId) -> &HeapData {
473
+ self.entries
474
+ .get(id.index())
475
+ .expect("Heap::get: slot missing")
476
+ .as_ref()
477
+ .expect("Heap::get: object already freed")
478
+ .data
479
+ .as_ref()
480
+ .expect("Heap::get: data currently borrowed")
481
+ }
482
+
483
+ /// Returns a mutable reference to the heap data stored at the given ID.
484
+ ///
485
+ /// # Panics
486
+ /// Panics if the value ID is invalid, the value has already been freed,
487
+ /// or the data is currently borrowed via `with_entry_mut`/`call_attr`.
488
+ pub fn get_mut(&mut self, id: HeapId) -> HeapDataMut<'_> {
489
+ self.entries
490
+ .get_mut(id.index())
491
+ .expect("Heap::get_mut: slot missing")
492
+ .as_mut()
493
+ .expect("Heap::get_mut: object already freed")
494
+ .data
495
+ .as_mut()
496
+ .expect("Heap::get_mut: data currently borrowed")
497
+ .to_mut()
498
+ }
499
+
500
+ /// Returns or computes the hash for the heap entry at the given ID.
501
+ ///
502
+ /// Hashes are computed lazily on first use and then cached. Returns
503
+ /// `Ok(Some(hash))` for immutable types, `Ok(None)` for mutable types,
504
+ /// or `Err(ResourceError::Recursion)` if the recursion limit is exceeded.
505
+ ///
506
+ /// # Panics
507
+ /// Panics if the value ID is invalid or the value has already been freed.
508
+ pub fn get_or_compute_hash(&mut self, id: HeapId, interns: &Interns) -> Result<Option<u64>, ResourceError> {
509
+ let entry = self
510
+ .entries
511
+ .get_mut(id.index())
512
+ .expect("Heap::get_or_compute_hash: slot missing")
513
+ .as_mut()
514
+ .expect("Heap::get_or_compute_hash: object already freed");
515
+
516
+ match entry.hash_state {
517
+ HashState::Unhashable => return Ok(None),
518
+ HashState::Cached(hash) => return Ok(Some(hash)),
519
+ HashState::Unknown => {}
520
+ }
521
+
522
+ // Handle Cell specially - uses identity-based hashing (like Python cell objects)
523
+ if let Some(HeapData::Cell(_)) = &entry.data {
524
+ let mut hasher = DefaultHasher::new();
525
+ id.hash(&mut hasher);
526
+ let hash = hasher.finish();
527
+ entry.hash_state = HashState::Cached(hash);
528
+ return Ok(Some(hash));
529
+ }
530
+
531
+ // Compute hash lazily - need to temporarily take data to avoid borrow conflict.
532
+ // IMPORTANT: data must be restored to the entry on ALL paths (including errors)
533
+ // to avoid dropping HeapData containing Value::Ref without proper cleanup.
534
+ let mut data = entry.data.take().expect("Heap::get_or_compute_hash: data borrowed");
535
+ let hash = data.to_mut().compute_hash_if_immutable(self, interns);
536
+
537
+ // Restore data before handling the result
538
+ let entry = self
539
+ .entries
540
+ .get_mut(id.index())
541
+ .expect("Heap::get_or_compute_hash: slot missing after compute")
542
+ .as_mut()
543
+ .expect("Heap::get_or_compute_hash: object freed during compute");
544
+ entry.data = Some(data);
545
+
546
+ // Now handle the result and cache if successful
547
+ let hash = hash?;
548
+ entry.hash_state = match hash {
549
+ Some(value) => HashState::Cached(value),
550
+ None => HashState::Unhashable,
551
+ };
552
+ Ok(hash)
553
+ }
554
+
555
+ /// Calls an attribute on the heap entry, returning an `CallResult` that may signal
556
+ /// OS, external, or method calls.
557
+ ///
558
+ /// Temporarily takes ownership of the payload to avoid borrow conflicts when attribute
559
+ /// implementations also need mutable heap access (e.g. for refcounting).
560
+ ///
561
+ /// Returns `CallResult` which may be:
562
+ /// - `Value(v)` - Method completed synchronously with value `v`
563
+ /// - `OsCall(func, args)` - Method needs OS operation; VM should yield to host
564
+ /// - `ExternalCall(id, args)` - Method needs external function call
565
+ /// - `MethodCall(name, args)` - Dataclass method call; VM should yield to host
566
+ pub fn call_attr(vm: &mut VM<'_, '_, T>, id: HeapId, attr: &EitherStr, args: ArgValues) -> RunResult<CallResult> {
567
+ // Take data out so the borrow of self.entries ends
568
+ let heap = &mut *vm.heap;
569
+ let mut data = take_data!(heap, id, "call_attr");
570
+
571
+ let result = data.py_call_attr(id, vm, attr, args);
572
+
573
+ // Restore data
574
+ let heap = &mut *vm.heap;
575
+ restore_data!(heap, id, data, "call_attr");
576
+ result
577
+ }
578
+
579
+ /// Gives mutable access to a heap entry while allowing reentrant heap usage
580
+ /// inside the closure (e.g. to read other values or allocate results).
581
+ ///
582
+ /// The data is temporarily taken from the heap entry, so the closure can safely
583
+ /// mutate both the entry data and the heap (e.g. to allocate new values).
584
+ /// The data is automatically restored after the closure completes.
585
+ pub fn with_entry_mut<'a, 'p, F, R>(vm: &mut VM<'a, 'p, T>, id: HeapId, f: F) -> R
586
+ where
587
+ F: FnOnce(&mut VM<'a, 'p, T>, HeapDataMut) -> R,
588
+ {
589
+ // Take data out in a block so the borrow of self.entries ends
590
+ let heap = &mut *vm.heap;
591
+ let mut data = take_data!(heap, id, "with_entry_mut");
592
+
593
+ let result = f(vm, data.to_mut());
594
+
595
+ // Restore data
596
+ let heap = &mut *vm.heap;
597
+ restore_data!(heap, id, data, "with_entry_mut");
598
+ result
599
+ }
600
+
601
+ /// Temporarily takes ownership of two heap entries so their data can be borrowed
602
+ /// simultaneously while still permitting mutable access to the VM (e.g. to
603
+ /// allocate results). Automatically restores both entries after the closure
604
+ /// finishes executing.
605
+ ///
606
+ /// This is a static method that takes `&mut VM` instead of `&mut self` so that
607
+ /// the closure receives `&mut VM` — matching the `with_entry_mut` pattern and
608
+ /// allowing the closure to call methods that need `vm` (e.g. `py_eq`).
609
+ pub fn with_two<'a, 'p, F, R>(vm: &mut VM<'a, 'p, T>, left: HeapId, right: HeapId, f: F) -> R
610
+ where
611
+ F: FnOnce(&mut VM<'a, 'p, T>, &HeapData, &HeapData) -> R,
612
+ {
613
+ if left == right {
614
+ // Same value - take data once and pass it twice
615
+ let heap = &mut *vm.heap;
616
+ let data = take_data!(heap, left, "with_two");
617
+
618
+ let result = f(vm, &data, &data);
619
+
620
+ let heap = &mut *vm.heap;
621
+ restore_data!(heap, left, data, "with_two");
622
+ result
623
+ } else {
624
+ // Different values - take both
625
+ let heap = &mut *vm.heap;
626
+ let left_data = take_data!(heap, left, "with_two (left)");
627
+ let right_data = take_data!(heap, right, "with_two (right)");
628
+
629
+ let result = f(vm, &left_data, &right_data);
630
+
631
+ // Restore in reverse order
632
+ let heap = &mut *vm.heap;
633
+ restore_data!(heap, right, right_data, "with_two (right)");
634
+ restore_data!(heap, left, left_data, "with_two (left)");
635
+ result
636
+ }
637
+ }
638
+
639
+ /// Returns the reference count for the heap entry at the given ID.
640
+ ///
641
+ /// This is primarily used for testing reference counting behavior.
642
+ ///
643
+ /// # Panics
644
+ /// Panics if the value ID is invalid or the value has already been freed.
645
+ #[must_use]
646
+ #[cfg(feature = "ref-count-return")]
647
+ pub fn get_refcount(&self, id: HeapId) -> usize {
648
+ self.entries
649
+ .get(id.index())
650
+ .expect("Heap::get_refcount: slot missing")
651
+ .as_ref()
652
+ .expect("Heap::get_refcount: object already freed")
653
+ .refcount
654
+ .get()
655
+ }
656
+
657
+ /// Returns the number of live (non-freed) values on the heap.
658
+ ///
659
+ /// This is primarily used for testing to verify that all heap entries
660
+ /// are accounted for in reference count tests.
661
+ ///
662
+ /// Excludes the empty tuple singleton since it's an internal optimization
663
+ /// detail that persists even when not explicitly used by user code.
664
+ #[must_use]
665
+ #[cfg(feature = "ref-count-return")]
666
+ pub fn entry_count(&self) -> usize {
667
+ // 1.. to skip index 0 which is the empty tuple singleton
668
+ self.entries[1..].iter().filter(|o| o.is_some()).count()
669
+ }
670
+
671
+ /// Helper for List in-place add: extends the destination vec with items from a heap list.
672
+ ///
673
+ /// This method exists to work around borrow checker limitations when List::py_iadd
674
+ /// needs to read from one heap entry while extending another. By keeping both
675
+ /// the read and the refcount increments within Heap's impl block, we can use the
676
+ /// take/restore pattern to avoid the lifetime propagation issues.
677
+ ///
678
+ /// Returns `true` if successful, `false` if the source ID is not a List.
679
+ pub fn iadd_extend_list(&mut self, source_id: HeapId, dest: &mut Vec<Value>) -> bool {
680
+ if let HeapData::List(list) = self.get(source_id) {
681
+ let items: Vec<Value> = list.as_slice().iter().map(|v| v.clone_with_heap(self)).collect();
682
+ dest.extend(items);
683
+ true
684
+ } else {
685
+ false
686
+ }
687
+ }
688
+
689
+ /// Multiplies a heap-allocated value by an `i64`.
690
+ ///
691
+ /// If `id` refers to a `LongInt`, performs integer multiplication with a size
692
+ /// pre-check. Otherwise, treats `id` as a sequence and `int_val` as the repeat
693
+ /// count. This avoids multiple `heap.get()` calls by looking up the data once.
694
+ ///
695
+ /// Returns `Ok(None)` if the heap entry is neither a LongInt nor a sequence type.
696
+ pub fn mult_ref_by_i64(&mut self, id: HeapId, int_val: i64) -> RunResult<Option<Value>> {
697
+ if let HeapData::LongInt(li) = self.get(id) {
698
+ check_mult_size(li.bits(), i64_bits(int_val), &self.tracker)?;
699
+ let result = LongInt::new(li.inner().clone()) * LongInt::from(int_val);
700
+ Ok(Some(result.into_value(self)?))
701
+ } else {
702
+ let count = i64_to_repeat_count(int_val)?;
703
+ self.mult_sequence(id, count)
704
+ }
705
+ }
706
+
707
+ /// Multiplies two heap-allocated values.
708
+ ///
709
+ /// Returns Ok(None) for unsupported type combinations.
710
+ pub fn mult_heap_values(&mut self, id1: HeapId, id2: HeapId) -> RunResult<Option<Value>> {
711
+ let (seq_id, count) = match (self.get(id1), self.get(id2)) {
712
+ (HeapData::LongInt(a), HeapData::LongInt(b)) => {
713
+ check_mult_size(a.bits(), b.bits(), &self.tracker)?;
714
+ let result = LongInt::new(a.inner() * b.inner());
715
+ return Ok(Some(result.into_value(self)?));
716
+ }
717
+ (HeapData::LongInt(li), _) => {
718
+ let count = longint_to_repeat_count(li)?;
719
+ (id2, count)
720
+ }
721
+ (_, HeapData::LongInt(li)) => {
722
+ let count = longint_to_repeat_count(li)?;
723
+ (id1, count)
724
+ }
725
+ _ => return Ok(None),
726
+ };
727
+
728
+ self.mult_sequence(seq_id, count)
729
+ }
730
+
731
+ /// Multiplies (repeats) a sequence by an integer count.
732
+ ///
733
+ /// This method handles sequence repetition for Python's `*` operator when applied
734
+ /// to sequences (str, bytes, list, tuple). It creates a new heap-allocated sequence
735
+ /// with the elements repeated `count` times.
736
+ ///
737
+ /// # Arguments
738
+ /// * `id` - HeapId of the sequence to repeat
739
+ /// * `count` - Number of times to repeat (0 returns empty sequence)
740
+ ///
741
+ /// # Returns
742
+ /// * `Ok(Some(Value))` - The new repeated sequence
743
+ /// * `Ok(None)` - If the heap entry is not a sequence type
744
+ /// * `Err` - If allocation fails due to resource limits
745
+ pub fn mult_sequence(&mut self, id: HeapId, count: usize) -> RunResult<Option<Value>> {
746
+ match self.get(id) {
747
+ HeapData::Str(s) => {
748
+ check_repeat_size(s.len(), count, &self.tracker)?;
749
+ Ok(Some(Value::Ref(
750
+ self.allocate(HeapData::Str(s.as_str().repeat(count).into()))?,
751
+ )))
752
+ }
753
+ HeapData::Bytes(b) => {
754
+ check_repeat_size(b.len(), count, &self.tracker)?;
755
+ Ok(Some(Value::Ref(
756
+ self.allocate(HeapData::Bytes(b.as_slice().repeat(count).into()))?,
757
+ )))
758
+ }
759
+ HeapData::List(list) => {
760
+ check_repeat_size(list.len().saturating_mul(size_of::<Value>()), count, &self.tracker)?;
761
+ let mut result = Vec::with_capacity(list.as_slice().len() * count);
762
+ for _ in 0..count {
763
+ result.extend(list.as_slice().iter().map(|v| v.clone_with_heap(self)));
764
+ self.check_time()?;
765
+ }
766
+ Ok(Some(Value::Ref(self.allocate(HeapData::List(List::new(result)))?)))
767
+ }
768
+ HeapData::Tuple(tuple) => {
769
+ if count == 0 {
770
+ return Ok(Some(self.get_empty_tuple()));
771
+ }
772
+ check_repeat_size(
773
+ tuple.as_slice().len().saturating_mul(size_of::<Value>()),
774
+ count,
775
+ &self.tracker,
776
+ )?;
777
+ let mut result = SmallVec::with_capacity(tuple.as_slice().len() * count);
778
+ for _ in 0..count {
779
+ result.extend(tuple.as_slice().iter().map(|v| v.clone_with_heap(self)));
780
+ self.check_time()?;
781
+ }
782
+ Ok(Some(allocate_tuple(result, self)?))
783
+ }
784
+ _ => Ok(None),
785
+ }
786
+ }
787
+
788
+ /// Returns whether garbage collection should run.
789
+ ///
790
+ /// True if reference cycles count exist in the heap
791
+ /// and the number of allocations since the last GC exceeds the interval.
792
+ #[inline]
793
+ pub fn should_gc(&self) -> bool {
794
+ self.may_have_cycles && self.allocations_since_gc >= GC_INTERVAL
795
+ }
796
+
797
+ /// Runs mark-sweep garbage collection to free unreachable cycles.
798
+ ///
799
+ /// This method takes a closure that provides an iterator of root HeapIds
800
+ /// (typically from the VM's globals and stack). It marks all reachable objects starting
801
+ /// from roots, then sweeps (frees) any unreachable objects.
802
+ ///
803
+ /// This is necessary because reference counting alone cannot free cycles
804
+ /// where objects reference each other but are unreachable from the program.
805
+ ///
806
+ /// # Caller Responsibility
807
+ /// The caller should check `should_gc()` before calling this method.
808
+ /// If no cycles are possible, the caller can skip GC entirely.
809
+ ///
810
+ /// # Arguments
811
+ /// * `root` - HeapIds that are roots
812
+ pub fn collect_garbage(&mut self, root: Vec<HeapId>) {
813
+ // Mark phase: collect all reachable IDs using BFS
814
+ // Use Vec<bool> instead of HashSet for O(1) operations without hashing overhead
815
+ let mut reachable: Vec<bool> = vec![false; self.entries.len()];
816
+ let mut work_list: Vec<HeapId> = root;
817
+
818
+ while let Some(id) = work_list.pop() {
819
+ let idx = id.index();
820
+ // Skip if out of bounds or already visited
821
+ if idx >= reachable.len() || reachable[idx] {
822
+ continue;
823
+ }
824
+ reachable[idx] = true;
825
+
826
+ // Add children to work list
827
+ if let Some(Some(entry)) = self.entries.get(idx)
828
+ && let Some(ref data) = entry.data
829
+ {
830
+ collect_child_ids(data, &mut work_list);
831
+ }
832
+ }
833
+
834
+ // Sweep phase: free unreachable values
835
+ for (id, value) in self.entries.iter_mut().enumerate() {
836
+ if reachable[id] {
837
+ continue;
838
+ }
839
+
840
+ // This entry is unreachable - free it
841
+ if let Some(value) = value.take() {
842
+ // Notify tracker of freed memory
843
+ if let Some(ref data) = value.data {
844
+ self.tracker.on_free(|| data.py_estimate_size());
845
+ }
846
+
847
+ self.free_list.push(HeapId(id));
848
+
849
+ // Mark Values as Dereferenced when ref-count-panic is enabled
850
+ #[cfg(feature = "ref-count-panic")]
851
+ if let Some(mut data) = value.data {
852
+ data.py_dec_ref_ids(&mut Vec::new());
853
+ }
854
+ }
855
+ }
856
+
857
+ // Reset cycle flag after GC - cycles have been collected
858
+ self.may_have_cycles = false;
859
+ self.allocations_since_gc = 0;
860
+ }
861
+ }
862
+
863
+ /// Computes the number of significant bits in an `i64`.
864
+ ///
865
+ /// Returns 0 for zero, otherwise returns the position of the highest set bit
866
+ /// plus one. Uses unsigned absolute value to handle negative numbers correctly.
867
+ fn i64_bits(value: i64) -> u64 {
868
+ if value == 0 {
869
+ 0
870
+ } else {
871
+ u64::from(64 - value.unsigned_abs().leading_zeros())
872
+ }
873
+ }
874
+
875
+ /// Converts an `i64` repeat count to `usize` for sequence repetition.
876
+ ///
877
+ /// Returns 0 for negative values (Python treats negative repeat counts as 0).
878
+ /// Returns `OverflowError` if the value exceeds `usize::MAX`.
879
+ fn i64_to_repeat_count(n: i64) -> RunResult<usize> {
880
+ if n <= 0 {
881
+ Ok(0)
882
+ } else {
883
+ usize::try_from(n).map_err(|_| ExcType::overflow_repeat_count().into())
884
+ }
885
+ }
886
+
887
+ /// Converts a `LongInt` repeat count to `usize` for sequence repetition.
888
+ ///
889
+ /// Returns 0 for negative values (Python treats negative repeat counts as 0).
890
+ /// Returns `OverflowError` if the value exceeds `usize::MAX`.
891
+ fn longint_to_repeat_count(li: &LongInt) -> RunResult<usize> {
892
+ if li.is_negative() {
893
+ Ok(0)
894
+ } else if let Some(count) = li.to_usize() {
895
+ Ok(count)
896
+ } else {
897
+ Err(ExcType::overflow_repeat_count().into())
898
+ }
899
+ }
900
+
901
+ /// Collects child HeapIds from a HeapData value for GC traversal.
902
+ fn collect_child_ids(data: &HeapData, work_list: &mut Vec<HeapId>) {
903
+ match data {
904
+ HeapData::List(list) => {
905
+ // Skip iteration if no refs - major GC optimization for lists of primitives
906
+ if !list.contains_refs() {
907
+ return;
908
+ }
909
+ for value in list.as_slice() {
910
+ if let Value::Ref(id) = value {
911
+ work_list.push(*id);
912
+ }
913
+ }
914
+ }
915
+ HeapData::Tuple(tuple) => {
916
+ // Skip iteration if no refs - GC optimization for tuples of primitives
917
+ if !tuple.contains_refs() {
918
+ return;
919
+ }
920
+ for value in tuple.as_slice() {
921
+ if let Value::Ref(id) = value {
922
+ work_list.push(*id);
923
+ }
924
+ }
925
+ }
926
+ HeapData::NamedTuple(nt) => {
927
+ // Skip iteration if no refs - GC optimization for namedtuples of primitives
928
+ if !nt.contains_refs() {
929
+ return;
930
+ }
931
+ for value in nt.as_vec() {
932
+ if let Value::Ref(id) = value {
933
+ work_list.push(*id);
934
+ }
935
+ }
936
+ }
937
+ HeapData::Dict(dict) => {
938
+ // Skip iteration if no refs - major GC optimization for dicts of primitives
939
+ if !dict.has_refs() {
940
+ return;
941
+ }
942
+ for (k, v) in dict {
943
+ if let Value::Ref(id) = k {
944
+ work_list.push(*id);
945
+ }
946
+ if let Value::Ref(id) = v {
947
+ work_list.push(*id);
948
+ }
949
+ }
950
+ }
951
+ HeapData::DictKeysView(view) => {
952
+ work_list.push(view.dict_id());
953
+ }
954
+ HeapData::DictItemsView(view) => {
955
+ work_list.push(view.dict_id());
956
+ }
957
+ HeapData::DictValuesView(view) => {
958
+ work_list.push(view.dict_id());
959
+ }
960
+ HeapData::Set(set) => {
961
+ for value in set.storage().iter() {
962
+ if let Value::Ref(id) = value {
963
+ work_list.push(*id);
964
+ }
965
+ }
966
+ }
967
+ HeapData::FrozenSet(frozenset) => {
968
+ for value in frozenset.storage().iter() {
969
+ if let Value::Ref(id) = value {
970
+ work_list.push(*id);
971
+ }
972
+ }
973
+ }
974
+ HeapData::Closure(closure) => {
975
+ // Add captured cells to work list
976
+ for cell_id in &closure.cells {
977
+ work_list.push(*cell_id);
978
+ }
979
+ // Add default values that are heap references
980
+ for default in &closure.defaults {
981
+ if let Value::Ref(id) = default {
982
+ work_list.push(*id);
983
+ }
984
+ }
985
+ }
986
+ HeapData::FunctionDefaults(fd) => {
987
+ // Add default values that are heap references
988
+ for default in &fd.defaults {
989
+ if let Value::Ref(id) = default {
990
+ work_list.push(*id);
991
+ }
992
+ }
993
+ }
994
+ HeapData::Cell(cell) => {
995
+ // Cell can contain a reference to another heap value
996
+ if let Value::Ref(id) = &cell.0 {
997
+ work_list.push(*id);
998
+ }
999
+ }
1000
+ HeapData::Dataclass(dc) => {
1001
+ // Dataclass attrs are stored in a Dict - iterate through entries
1002
+ for (k, v) in dc.attrs() {
1003
+ if let Value::Ref(id) = k {
1004
+ work_list.push(*id);
1005
+ }
1006
+ if let Value::Ref(id) = v {
1007
+ work_list.push(*id);
1008
+ }
1009
+ }
1010
+ }
1011
+ HeapData::Iter(iter) => {
1012
+ // Iterator holds a reference to the iterable being iterated
1013
+ if let Value::Ref(id) = iter.value() {
1014
+ work_list.push(*id);
1015
+ }
1016
+ }
1017
+ HeapData::Module(m) => {
1018
+ // Module attrs can contain references to heap values
1019
+ if !m.has_refs() {
1020
+ return;
1021
+ }
1022
+ for (k, v) in m.attrs() {
1023
+ if let Value::Ref(id) = k {
1024
+ work_list.push(*id);
1025
+ }
1026
+ if let Value::Ref(id) = v {
1027
+ work_list.push(*id);
1028
+ }
1029
+ }
1030
+ }
1031
+ HeapData::Coroutine(coro) => {
1032
+ // Add namespace values that are heap references
1033
+ for value in &coro.namespace {
1034
+ if let Value::Ref(id) = value {
1035
+ work_list.push(*id);
1036
+ }
1037
+ }
1038
+ }
1039
+ HeapData::GatherFuture(gather) => {
1040
+ // Add coroutine HeapIds to work list
1041
+ for item in &gather.items {
1042
+ if let GatherItem::Coroutine(coro_id) = item {
1043
+ work_list.push(*coro_id);
1044
+ }
1045
+ }
1046
+ // Add result values that are heap references
1047
+ for result in gather.results.iter().flatten() {
1048
+ if let Value::Ref(id) = result {
1049
+ work_list.push(*id);
1050
+ }
1051
+ }
1052
+ }
1053
+ // Leaf types with no heap references
1054
+ _ => {}
1055
+ }
1056
+ }
1057
+
1058
+ /// Drop implementation for Heap that marks all contained Objects as Dereferenced
1059
+ /// before dropping to prevent panics when the `ref-count-panic` feature is enabled.
1060
+ #[cfg(feature = "ref-count-panic")]
1061
+ impl<T: ResourceTracker> Drop for Heap<T> {
1062
+ fn drop(&mut self) {
1063
+ // Mark all contained Objects as Dereferenced before dropping.
1064
+ // We use py_dec_ref_ids for this since it handles the marking
1065
+ // (we ignore the collected IDs since we're dropping everything anyway).
1066
+ let mut dummy_stack = Vec::new();
1067
+ for value in self.entries.iter_mut().flatten() {
1068
+ if let Some(data) = &mut value.data {
1069
+ data.py_dec_ref_ids(&mut dummy_stack);
1070
+ }
1071
+ }
1072
+ }
1073
+ }