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.
- package/__tests__/adapter-schema.test.js +2 -0
- package/__tests__/config.test.js +62 -1
- package/__tests__/help-json.test.js +2 -0
- package/__tests__/mcp-adapter.test.js +14 -4
- package/__tests__/mcp-local.test.js +159 -0
- package/__tests__/mcp-stdio-jsonrpc.test.js +105 -0
- package/__tests__/monty-plugin.test.js +121 -0
- package/__tests__/plugin-browser-use-uninstall.test.js +23 -0
- package/__tests__/plugin-browser-use.test.js +77 -0
- package/__tests__/plugins-command.test.js +92 -1
- package/__tests__/plugins-learn.test.js +62 -0
- package/__tests__/plugins-registry.test.js +3 -1
- package/__tests__/resend-plugin.test.js +122 -0
- package/__tests__/skills.test.js +4 -0
- package/cli/adapter-schema.js +3 -2
- package/cli/adapters/mcp.js +22 -3
- package/cli/adapters/process.js +34 -7
- package/cli/config.js +27 -1
- package/cli/help-json.js +2 -2
- package/cli/mcp-diagnostics.js +152 -0
- package/cli/mcp-discovery.js +221 -0
- package/cli/mcp-local.js +267 -25
- package/cli/mcp-stdio-jsonrpc.js +246 -0
- package/cli/plugin-install-guidance.js +25 -0
- package/cli/plugins-command.js +86 -3
- package/cli/plugins-learn.js +177 -0
- package/cli/plugins-manager.js +3 -0
- package/cli/plugins-registry.js +2 -1
- package/cli/skills-mcp.js +102 -0
- package/cli/skills.js +6 -40
- package/cli/supercli.js +7 -2
- package/docs/initial/mcp-local-mode.md +35 -0
- package/docs/mcp-cheatsheet.md +324 -0
- package/docs/plugins.md +7 -0
- package/package.json +1 -1
- package/plugins/browser-use/plugin.json +23 -0
- package/plugins/browser-use/scripts/post-install.js +146 -0
- package/plugins/browser-use/scripts/post-uninstall.js +28 -0
- package/plugins/browser-use/skills/quickstart/SKILL.md +47 -0
- package/plugins/monty/README.md +49 -0
- package/plugins/monty/plugin.json +69 -0
- package/plugins/monty/scripts/post-install.js +73 -0
- package/plugins/monty/scripts/post-uninstall.js +23 -0
- package/plugins/monty/scripts/run-python.js +140 -0
- package/plugins/monty/scripts/setup-monty.js +27 -0
- package/plugins/plugins.json +29 -0
- package/plugins/resend/plugin.json +371 -0
- package/plugins/resend/scripts/post-install.js +59 -0
- package/plugins/resend/scripts/post-uninstall.js +23 -0
- package/plugins/resend/scripts/setup-resend.js +27 -0
- package/plugins/resend/skills/quickstart/SKILL.md +80 -0
- package/ref-monty/.cargo/config.toml +3 -0
- package/ref-monty/.claude/settings.json +60 -0
- package/ref-monty/.claude/skills/fastmod/SKILL.md +22 -0
- package/ref-monty/.claude/skills/python-playground/SKILL.md +47 -0
- package/ref-monty/.codecov.yml +12 -0
- package/ref-monty/.github/actions/build-pgo-wheel/action.yml +72 -0
- package/ref-monty/.github/workflows/ci.yml +776 -0
- package/ref-monty/.github/workflows/codspeed.yml +45 -0
- package/ref-monty/.github/workflows/init-npm-packages.yml +82 -0
- package/ref-monty/.pre-commit-config.yaml +47 -0
- package/ref-monty/.python-version +1 -0
- package/ref-monty/.rustfmt.toml +4 -0
- package/ref-monty/.zed/settings.json +11 -0
- package/ref-monty/CLAUDE.md +535 -0
- package/ref-monty/Cargo.lock +3798 -0
- package/ref-monty/Cargo.toml +87 -0
- package/ref-monty/LICENSE +21 -0
- package/ref-monty/Makefile +216 -0
- package/ref-monty/README.md +430 -0
- package/ref-monty/RELEASING.md +47 -0
- package/ref-monty/crates/fuzz/Cargo.toml +30 -0
- package/ref-monty/crates/fuzz/fuzz_targets/string_input_panic.rs +37 -0
- package/ref-monty/crates/fuzz/fuzz_targets/tokens_input_panic.rs +552 -0
- package/ref-monty/crates/monty/Cargo.toml +68 -0
- package/ref-monty/crates/monty/benches/main.rs +247 -0
- package/ref-monty/crates/monty/build.rs +10 -0
- package/ref-monty/crates/monty/src/args.rs +733 -0
- package/ref-monty/crates/monty/src/asyncio.rs +179 -0
- package/ref-monty/crates/monty/src/builtins/abs.rs +55 -0
- package/ref-monty/crates/monty/src/builtins/all.rs +30 -0
- package/ref-monty/crates/monty/src/builtins/any.rs +30 -0
- package/ref-monty/crates/monty/src/builtins/bin.rs +59 -0
- package/ref-monty/crates/monty/src/builtins/chr.rs +46 -0
- package/ref-monty/crates/monty/src/builtins/divmod.rs +164 -0
- package/ref-monty/crates/monty/src/builtins/enumerate.rs +52 -0
- package/ref-monty/crates/monty/src/builtins/filter.rs +67 -0
- package/ref-monty/crates/monty/src/builtins/getattr.rs +65 -0
- package/ref-monty/crates/monty/src/builtins/hash.rs +28 -0
- package/ref-monty/crates/monty/src/builtins/hex.rs +58 -0
- package/ref-monty/crates/monty/src/builtins/id.rs +24 -0
- package/ref-monty/crates/monty/src/builtins/isinstance.rs +68 -0
- package/ref-monty/crates/monty/src/builtins/len.rs +25 -0
- package/ref-monty/crates/monty/src/builtins/map.rs +98 -0
- package/ref-monty/crates/monty/src/builtins/min_max.rs +113 -0
- package/ref-monty/crates/monty/src/builtins/mod.rs +246 -0
- package/ref-monty/crates/monty/src/builtins/next.rs +21 -0
- package/ref-monty/crates/monty/src/builtins/oct.rs +59 -0
- package/ref-monty/crates/monty/src/builtins/ord.rs +67 -0
- package/ref-monty/crates/monty/src/builtins/pow.rs +365 -0
- package/ref-monty/crates/monty/src/builtins/print.rs +141 -0
- package/ref-monty/crates/monty/src/builtins/repr.rs +16 -0
- package/ref-monty/crates/monty/src/builtins/reversed.rs +28 -0
- package/ref-monty/crates/monty/src/builtins/round.rs +174 -0
- package/ref-monty/crates/monty/src/builtins/sorted.rs +151 -0
- package/ref-monty/crates/monty/src/builtins/sum.rs +66 -0
- package/ref-monty/crates/monty/src/builtins/type_.rs +16 -0
- package/ref-monty/crates/monty/src/builtins/zip.rs +77 -0
- package/ref-monty/crates/monty/src/bytecode/builder.rs +699 -0
- package/ref-monty/crates/monty/src/bytecode/code.rs +310 -0
- package/ref-monty/crates/monty/src/bytecode/compiler.rs +3206 -0
- package/ref-monty/crates/monty/src/bytecode/mod.rs +24 -0
- package/ref-monty/crates/monty/src/bytecode/op.rs +617 -0
- package/ref-monty/crates/monty/src/bytecode/vm/async_exec.rs +1058 -0
- package/ref-monty/crates/monty/src/bytecode/vm/attr.rs +63 -0
- package/ref-monty/crates/monty/src/bytecode/vm/binary.rs +487 -0
- package/ref-monty/crates/monty/src/bytecode/vm/call.rs +767 -0
- package/ref-monty/crates/monty/src/bytecode/vm/collections.rs +741 -0
- package/ref-monty/crates/monty/src/bytecode/vm/compare.rs +147 -0
- package/ref-monty/crates/monty/src/bytecode/vm/exceptions.rs +297 -0
- package/ref-monty/crates/monty/src/bytecode/vm/format.rs +132 -0
- package/ref-monty/crates/monty/src/bytecode/vm/mod.rs +1958 -0
- package/ref-monty/crates/monty/src/bytecode/vm/scheduler.rs +620 -0
- package/ref-monty/crates/monty/src/exception_private.rs +1513 -0
- package/ref-monty/crates/monty/src/exception_public.rs +346 -0
- package/ref-monty/crates/monty/src/expressions.rs +694 -0
- package/ref-monty/crates/monty/src/fstring.rs +854 -0
- package/ref-monty/crates/monty/src/function.rs +119 -0
- package/ref-monty/crates/monty/src/heap.rs +1073 -0
- package/ref-monty/crates/monty/src/heap_data.rs +985 -0
- package/ref-monty/crates/monty/src/heap_traits.rs +312 -0
- package/ref-monty/crates/monty/src/intern.rs +837 -0
- package/ref-monty/crates/monty/src/io.rs +106 -0
- package/ref-monty/crates/monty/src/lib.rs +52 -0
- package/ref-monty/crates/monty/src/modules/asyncio.rs +144 -0
- package/ref-monty/crates/monty/src/modules/math.rs +1453 -0
- package/ref-monty/crates/monty/src/modules/mod.rs +120 -0
- package/ref-monty/crates/monty/src/modules/os.rs +116 -0
- package/ref-monty/crates/monty/src/modules/pathlib.rs +33 -0
- package/ref-monty/crates/monty/src/modules/re.rs +606 -0
- package/ref-monty/crates/monty/src/modules/sys.rs +60 -0
- package/ref-monty/crates/monty/src/modules/typing.rs +70 -0
- package/ref-monty/crates/monty/src/namespace.rs +21 -0
- package/ref-monty/crates/monty/src/object.rs +1040 -0
- package/ref-monty/crates/monty/src/os.rs +215 -0
- package/ref-monty/crates/monty/src/parse.rs +1730 -0
- package/ref-monty/crates/monty/src/prepare.rs +3015 -0
- package/ref-monty/crates/monty/src/repl.rs +1109 -0
- package/ref-monty/crates/monty/src/resource.rs +559 -0
- package/ref-monty/crates/monty/src/run.rs +457 -0
- package/ref-monty/crates/monty/src/run_progress.rs +821 -0
- package/ref-monty/crates/monty/src/signature.rs +651 -0
- package/ref-monty/crates/monty/src/sorting.rs +100 -0
- package/ref-monty/crates/monty/src/types/bytes.rs +2356 -0
- package/ref-monty/crates/monty/src/types/dataclass.rs +345 -0
- package/ref-monty/crates/monty/src/types/dict.rs +879 -0
- package/ref-monty/crates/monty/src/types/dict_view.rs +619 -0
- package/ref-monty/crates/monty/src/types/iter.rs +799 -0
- package/ref-monty/crates/monty/src/types/list.rs +929 -0
- package/ref-monty/crates/monty/src/types/long_int.rs +211 -0
- package/ref-monty/crates/monty/src/types/mod.rs +48 -0
- package/ref-monty/crates/monty/src/types/module.rs +146 -0
- package/ref-monty/crates/monty/src/types/namedtuple.rs +261 -0
- package/ref-monty/crates/monty/src/types/path.rs +596 -0
- package/ref-monty/crates/monty/src/types/property.rs +35 -0
- package/ref-monty/crates/monty/src/types/py_trait.rs +322 -0
- package/ref-monty/crates/monty/src/types/range.rs +285 -0
- package/ref-monty/crates/monty/src/types/re_match.rs +522 -0
- package/ref-monty/crates/monty/src/types/re_pattern.rs +726 -0
- package/ref-monty/crates/monty/src/types/set.rs +1373 -0
- package/ref-monty/crates/monty/src/types/slice.rs +257 -0
- package/ref-monty/crates/monty/src/types/str.rs +2051 -0
- package/ref-monty/crates/monty/src/types/tuple.rs +376 -0
- package/ref-monty/crates/monty/src/types/type.rs +407 -0
- package/ref-monty/crates/monty/src/value.rs +2558 -0
- package/ref-monty/crates/monty/test_cases/args__dict_get_no_args.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__dict_get_too_many.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__dict_items_with_args.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__dict_keys_with_args.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__dict_pop_no_args.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__dict_pop_too_many.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__dict_values_with_args.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__id_too_many.py +2 -0
- package/ref-monty/crates/monty/test_cases/args__len_no_args.py +2 -0
- package/ref-monty/crates/monty/test_cases/args__len_too_many.py +2 -0
- package/ref-monty/crates/monty/test_cases/args__len_type_error_int.py +9 -0
- package/ref-monty/crates/monty/test_cases/args__len_type_error_none.py +9 -0
- package/ref-monty/crates/monty/test_cases/args__list_append_no_args.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__list_append_too_many.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__list_insert_too_few.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__list_insert_too_many.py +3 -0
- package/ref-monty/crates/monty/test_cases/args__repr_no_args.py +2 -0
- package/ref-monty/crates/monty/test_cases/arith__div_zero_float.py +2 -0
- package/ref-monty/crates/monty/test_cases/arith__div_zero_int.py +2 -0
- package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_float.py +2 -0
- package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_int.py +2 -0
- package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg.py +2 -0
- package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg_builtin.py +9 -0
- package/ref-monty/crates/monty/test_cases/assert__expr_fail.py +2 -0
- package/ref-monty/crates/monty/test_cases/assert__fail.py +2 -0
- package/ref-monty/crates/monty/test_cases/assert__fail_msg.py +2 -0
- package/ref-monty/crates/monty/test_cases/assert__fn_fail.py +3 -0
- package/ref-monty/crates/monty/test_cases/assert__ops.py +11 -0
- package/ref-monty/crates/monty/test_cases/async__asyncio_run.py +47 -0
- package/ref-monty/crates/monty/test_cases/async__basic.py +10 -0
- package/ref-monty/crates/monty/test_cases/async__closure.py +14 -0
- package/ref-monty/crates/monty/test_cases/async__double_await_coroutine.py +16 -0
- package/ref-monty/crates/monty/test_cases/async__exception.py +10 -0
- package/ref-monty/crates/monty/test_cases/async__ext_call.py +73 -0
- package/ref-monty/crates/monty/test_cases/async__gather_all.py +85 -0
- package/ref-monty/crates/monty/test_cases/async__nested_await.py +15 -0
- package/ref-monty/crates/monty/test_cases/async__nested_gather_ext.py +37 -0
- package/ref-monty/crates/monty/test_cases/async__not_awaitable.py +10 -0
- package/ref-monty/crates/monty/test_cases/async__not_imported.py +14 -0
- package/ref-monty/crates/monty/test_cases/async__recursion_depth_isolation.py +27 -0
- package/ref-monty/crates/monty/test_cases/async__return_types.py +31 -0
- package/ref-monty/crates/monty/test_cases/async__sequential.py +16 -0
- package/ref-monty/crates/monty/test_cases/async__traceback.py +19 -0
- package/ref-monty/crates/monty/test_cases/async__with_args.py +14 -0
- package/ref-monty/crates/monty/test_cases/attr__get_int_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/attr__get_list_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/attr__set_frozen_nonfield.py +12 -0
- package/ref-monty/crates/monty/test_cases/attr__set_int_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/attr__set_list_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/bench__kitchen_sink.py +68 -0
- package/ref-monty/crates/monty/test_cases/bool__ops.py +20 -0
- package/ref-monty/crates/monty/test_cases/builtin__add_type_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/builtin__filter.py +62 -0
- package/ref-monty/crates/monty/test_cases/builtin__filter_not_iterable.py +11 -0
- package/ref-monty/crates/monty/test_cases/builtin__getattr.py +84 -0
- package/ref-monty/crates/monty/test_cases/builtin__iter_funcs.py +42 -0
- package/ref-monty/crates/monty/test_cases/builtin__iter_next.py +66 -0
- package/ref-monty/crates/monty/test_cases/builtin__map.py +74 -0
- package/ref-monty/crates/monty/test_cases/builtin__map_not_iterable.py +11 -0
- package/ref-monty/crates/monty/test_cases/builtin__math_funcs.py +154 -0
- package/ref-monty/crates/monty/test_cases/builtin__more_iter_funcs.py +148 -0
- package/ref-monty/crates/monty/test_cases/builtin__next_stop_iteration.py +10 -0
- package/ref-monty/crates/monty/test_cases/builtin__print_invalid_kwarg.py +9 -0
- package/ref-monty/crates/monty/test_cases/builtin__print_kwargs.py +12 -0
- package/ref-monty/crates/monty/test_cases/builtin__repr.py +3 -0
- package/ref-monty/crates/monty/test_cases/builtin__string_funcs.py +73 -0
- package/ref-monty/crates/monty/test_cases/bytes__decode_invalid_utf8.py +18 -0
- package/ref-monty/crates/monty/test_cases/bytes__endswith_str_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/bytes__getitem_index_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/bytes__index_start_gt_end.py +10 -0
- package/ref-monty/crates/monty/test_cases/bytes__methods.py +394 -0
- package/ref-monty/crates/monty/test_cases/bytes__negative_count.py +9 -0
- package/ref-monty/crates/monty/test_cases/bytes__ops.py +90 -0
- package/ref-monty/crates/monty/test_cases/bytes__startswith_str_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/call_object.py +3 -0
- package/ref-monty/crates/monty/test_cases/chain_comparison__all.py +79 -0
- package/ref-monty/crates/monty/test_cases/closure__param_shadows_outer.py +81 -0
- package/ref-monty/crates/monty/test_cases/closure__pep448.py +203 -0
- package/ref-monty/crates/monty/test_cases/closure__undefined_nonlocal.py +13 -0
- package/ref-monty/crates/monty/test_cases/compare__mixed_types.py +120 -0
- package/ref-monty/crates/monty/test_cases/comprehension__all.py +208 -0
- package/ref-monty/crates/monty/test_cases/comprehension__scope.py +7 -0
- package/ref-monty/crates/monty/test_cases/comprehension__unbound_local.py +14 -0
- package/ref-monty/crates/monty/test_cases/dataclass__basic.py +238 -0
- package/ref-monty/crates/monty/test_cases/dataclass__call_field_error.py +12 -0
- package/ref-monty/crates/monty/test_cases/dataclass__frozen_set_error.py +12 -0
- package/ref-monty/crates/monty/test_cases/dataclass__get_missing_attr_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/dict__get_unhashable_key.py +3 -0
- package/ref-monty/crates/monty/test_cases/dict__literal_unhashable_key.py +2 -0
- package/ref-monty/crates/monty/test_cases/dict__method_pop_missing_error.py +3 -0
- package/ref-monty/crates/monty/test_cases/dict__methods.py +151 -0
- package/ref-monty/crates/monty/test_cases/dict__ops.py +133 -0
- package/ref-monty/crates/monty/test_cases/dict__pop_unhashable_key.py +4 -0
- package/ref-monty/crates/monty/test_cases/dict__popitem_empty.py +9 -0
- package/ref-monty/crates/monty/test_cases/dict__subscript_missing_key.py +3 -0
- package/ref-monty/crates/monty/test_cases/dict__unhashable_dict_key.py +2 -0
- package/ref-monty/crates/monty/test_cases/dict__unhashable_list_key.py +2 -0
- package/ref-monty/crates/monty/test_cases/dict__unpack_type_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/dict__views.py +165 -0
- package/ref-monty/crates/monty/test_cases/edge__all.py +26 -0
- package/ref-monty/crates/monty/test_cases/edge__float_int_mod.py +2 -0
- package/ref-monty/crates/monty/test_cases/edge__int_float_mod.py +2 -0
- package/ref-monty/crates/monty/test_cases/exc__args.py +16 -0
- package/ref-monty/crates/monty/test_cases/exc__str.py +15 -0
- package/ref-monty/crates/monty/test_cases/execute_ok__all.py +54 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__error_instance_str.py +2 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__error_no_args.py +2 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg.py +2 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg_quotes.py +2 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__error_type.py +2 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__raise_instance_via_var.py +4 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__raise_list.py +2 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__raise_number.py +2 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_call_via_var.py +4 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_direct.py +3 -0
- package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_via_var.py +4 -0
- package/ref-monty/crates/monty/test_cases/ext_call__arg_side_effect_bug.py +22 -0
- package/ref-monty/crates/monty/test_cases/ext_call__augmented.py +17 -0
- package/ref-monty/crates/monty/test_cases/ext_call__augmented_refcount_bug.py +7 -0
- package/ref-monty/crates/monty/test_cases/ext_call__bare_raise_after_resume.py +34 -0
- package/ref-monty/crates/monty/test_cases/ext_call__basic.py +99 -0
- package/ref-monty/crates/monty/test_cases/ext_call__boolean.py +37 -0
- package/ref-monty/crates/monty/test_cases/ext_call__boolean_side_effect_hang.py +17 -0
- package/ref-monty/crates/monty/test_cases/ext_call__closure_bug.py +16 -0
- package/ref-monty/crates/monty/test_cases/ext_call__comparison.py +26 -0
- package/ref-monty/crates/monty/test_cases/ext_call__deep_call_stack.py +18 -0
- package/ref-monty/crates/monty/test_cases/ext_call__elif.py +171 -0
- package/ref-monty/crates/monty/test_cases/ext_call__exc.py +4 -0
- package/ref-monty/crates/monty/test_cases/ext_call__exc_deep_stack.py +39 -0
- package/ref-monty/crates/monty/test_cases/ext_call__exc_in_function.py +17 -0
- package/ref-monty/crates/monty/test_cases/ext_call__exc_nested_functions.py +31 -0
- package/ref-monty/crates/monty/test_cases/ext_call__ext_exc.py +171 -0
- package/ref-monty/crates/monty/test_cases/ext_call__for.py +114 -0
- package/ref-monty/crates/monty/test_cases/ext_call__fstring.py +12 -0
- package/ref-monty/crates/monty/test_cases/ext_call__if.py +135 -0
- package/ref-monty/crates/monty/test_cases/ext_call__if_condition.py +37 -0
- package/ref-monty/crates/monty/test_cases/ext_call__in_closure.py +14 -0
- package/ref-monty/crates/monty/test_cases/ext_call__in_function.py +40 -0
- package/ref-monty/crates/monty/test_cases/ext_call__in_function_simple.py +7 -0
- package/ref-monty/crates/monty/test_cases/ext_call__literals.py +17 -0
- package/ref-monty/crates/monty/test_cases/ext_call__multi_in_func.py +32 -0
- package/ref-monty/crates/monty/test_cases/ext_call__name_lookup.py +69 -0
- package/ref-monty/crates/monty/test_cases/ext_call__name_lookup_undefined.py +4 -0
- package/ref-monty/crates/monty/test_cases/ext_call__nested_calls.py +14 -0
- package/ref-monty/crates/monty/test_cases/ext_call__recursion_bug.py +19 -0
- package/ref-monty/crates/monty/test_cases/ext_call__return.py +28 -0
- package/ref-monty/crates/monty/test_cases/ext_call__side_effects.py +25 -0
- package/ref-monty/crates/monty/test_cases/ext_call__subscript.py +7 -0
- package/ref-monty/crates/monty/test_cases/ext_call__ternary.py +28 -0
- package/ref-monty/crates/monty/test_cases/ext_call__try.py +280 -0
- package/ref-monty/crates/monty/test_cases/ext_call__try_simple.py +10 -0
- package/ref-monty/crates/monty/test_cases/ext_call__unary.py +13 -0
- package/ref-monty/crates/monty/test_cases/frozenset__ops.py +178 -0
- package/ref-monty/crates/monty/test_cases/fstring__all.py +236 -0
- package/ref-monty/crates/monty/test_cases/fstring__error_eq_align_on_str.py +3 -0
- package/ref-monty/crates/monty/test_cases/fstring__error_float_f_on_str.py +3 -0
- package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_float.py +3 -0
- package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_str.py +3 -0
- package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec.py +4 -0
- package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_dynamic.py +4 -0
- package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_str.py +4 -0
- package/ref-monty/crates/monty/test_cases/fstring__error_str_s_on_int.py +3 -0
- package/ref-monty/crates/monty/test_cases/function__call_duplicate_kwargs.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__call_unpack.py +42 -0
- package/ref-monty/crates/monty/test_cases/function__defaults.py +117 -0
- package/ref-monty/crates/monty/test_cases/function__err_duplicate_arg.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_duplicate_first_arg.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_duplicate_kwarg_cleanup.py +9 -0
- package/ref-monty/crates/monty/test_cases/function__err_kwonly_as_positional.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_missing_all_posonly.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_missing_heap_cleanup.py +9 -0
- package/ref-monty/crates/monty/test_cases/function__err_missing_kwonly.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_missing_posonly_with_kwarg.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_missing_with_posonly.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_posonly_as_kwarg.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_posonly_first_as_kwarg.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_too_many_posonly.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_too_many_with_kwonly.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_cleanup.py +9 -0
- package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_quote.py +13 -0
- package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_simple.py +7 -0
- package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_arg.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_heap.py +8 -0
- package/ref-monty/crates/monty/test_cases/function__err_unpack_int.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__err_unpack_nonstring_key.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__err_unpack_not_mapping.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__kwargs_unpacking.py +173 -0
- package/ref-monty/crates/monty/test_cases/function__ops.py +294 -0
- package/ref-monty/crates/monty/test_cases/function__return_none.py +42 -0
- package/ref-monty/crates/monty/test_cases/function__signatures.py +47 -0
- package/ref-monty/crates/monty/test_cases/function__too_few_args_all.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__too_few_args_one.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__too_few_args_two.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__too_many_args_one.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__too_many_args_two.py +6 -0
- package/ref-monty/crates/monty/test_cases/function__too_many_args_zero.py +6 -0
- package/ref-monty/crates/monty/test_cases/global__error_assigned_before.py +7 -0
- package/ref-monty/crates/monty/test_cases/global__ops.py +163 -0
- package/ref-monty/crates/monty/test_cases/hash__dict_unhashable.py +2 -0
- package/ref-monty/crates/monty/test_cases/hash__list_unhashable.py +2 -0
- package/ref-monty/crates/monty/test_cases/hash__ops.py +153 -0
- package/ref-monty/crates/monty/test_cases/id__bytes_literals_distinct.py +3 -0
- package/ref-monty/crates/monty/test_cases/id__int_copy_distinct.py +5 -0
- package/ref-monty/crates/monty/test_cases/id__is_number_is_number.py +3 -0
- package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_distinct_types.py +10 -0
- package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_same_types.py +6 -0
- package/ref-monty/crates/monty/test_cases/id__ops.py +97 -0
- package/ref-monty/crates/monty/test_cases/id__str_literals_same.py +3 -0
- package/ref-monty/crates/monty/test_cases/if__elif_else.py +207 -0
- package/ref-monty/crates/monty/test_cases/if__raise_elif.py +11 -0
- package/ref-monty/crates/monty/test_cases/if__raise_else.py +13 -0
- package/ref-monty/crates/monty/test_cases/if__raise_if.py +9 -0
- package/ref-monty/crates/monty/test_cases/if__raise_in_elif_condition.py +18 -0
- package/ref-monty/crates/monty/test_cases/if__raise_in_if_condition.py +16 -0
- package/ref-monty/crates/monty/test_cases/if_else_expr__all.py +55 -0
- package/ref-monty/crates/monty/test_cases/import__error_cannot_import.py +9 -0
- package/ref-monty/crates/monty/test_cases/import__error_module_not_found.py +9 -0
- package/ref-monty/crates/monty/test_cases/import__local_scope.py +68 -0
- package/ref-monty/crates/monty/test_cases/import__os.py +25 -0
- package/ref-monty/crates/monty/test_cases/import__relative_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/import__relative_no_module_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/import__runtime_error_when_executed.py +14 -0
- package/ref-monty/crates/monty/test_cases/import__star_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/import__sys.py +47 -0
- package/ref-monty/crates/monty/test_cases/import__sys_monty.py +28 -0
- package/ref-monty/crates/monty/test_cases/import__type_checking_guard.py +37 -0
- package/ref-monty/crates/monty/test_cases/import__typing.py +25 -0
- package/ref-monty/crates/monty/test_cases/import__typing_type_ignore.py +4 -0
- package/ref-monty/crates/monty/test_cases/int__bigint.py +467 -0
- package/ref-monty/crates/monty/test_cases/int__bigint_errors.py +260 -0
- package/ref-monty/crates/monty/test_cases/int__ops.py +219 -0
- package/ref-monty/crates/monty/test_cases/int__overflow_division.py +84 -0
- package/ref-monty/crates/monty/test_cases/is_variant__all.py +36 -0
- package/ref-monty/crates/monty/test_cases/isinstance__arg2_list_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/isinstance__arg2_type_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/iter__dict_mutation.py +4 -0
- package/ref-monty/crates/monty/test_cases/iter__for.py +243 -0
- package/ref-monty/crates/monty/test_cases/iter__for_loop_unpacking.py +66 -0
- package/ref-monty/crates/monty/test_cases/iter__generator_expr.py +20 -0
- package/ref-monty/crates/monty/test_cases/iter__generator_expr_type.py +7 -0
- package/ref-monty/crates/monty/test_cases/iter__not_iterable.py +3 -0
- package/ref-monty/crates/monty/test_cases/lambda__all.py +145 -0
- package/ref-monty/crates/monty/test_cases/list__extend_not_iterable.py +7 -0
- package/ref-monty/crates/monty/test_cases/list__getitem_out_of_bounds.py +3 -0
- package/ref-monty/crates/monty/test_cases/list__index_not_found.py +9 -0
- package/ref-monty/crates/monty/test_cases/list__index_start_gt_end.py +10 -0
- package/ref-monty/crates/monty/test_cases/list__ops.py +473 -0
- package/ref-monty/crates/monty/test_cases/list__pop_empty.py +9 -0
- package/ref-monty/crates/monty/test_cases/list__pop_out_of_range.py +9 -0
- package/ref-monty/crates/monty/test_cases/list__pop_type_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/list__remove_not_found.py +9 -0
- package/ref-monty/crates/monty/test_cases/list__setitem_dict_index.py +13 -0
- package/ref-monty/crates/monty/test_cases/list__setitem_huge_int_index.py +13 -0
- package/ref-monty/crates/monty/test_cases/list__setitem_index_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/list__setitem_type_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/list__unpack_type_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/longint__index_error.py +3 -0
- package/ref-monty/crates/monty/test_cases/longint__repeat_error.py +3 -0
- package/ref-monty/crates/monty/test_cases/loop__break_continue.py +113 -0
- package/ref-monty/crates/monty/test_cases/loop__break_finally.py +69 -0
- package/ref-monty/crates/monty/test_cases/loop__break_in_function_error.py +13 -0
- package/ref-monty/crates/monty/test_cases/loop__break_in_if_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/loop__break_nested_except_clears.py +55 -0
- package/ref-monty/crates/monty/test_cases/loop__break_outside_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/loop__continue_finally.py +81 -0
- package/ref-monty/crates/monty/test_cases/loop__continue_in_function_error.py +13 -0
- package/ref-monty/crates/monty/test_cases/loop__continue_in_if_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/loop__continue_nested_except_clears.py +60 -0
- package/ref-monty/crates/monty/test_cases/loop__continue_outside_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/math__acos_domain_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__acosh_domain_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__asin_domain_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__atanh_domain_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__cos_inf_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__cosh_overflow_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__exp_overflow_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__factorial_float_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__factorial_negative_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__floor_inf_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__floor_nan_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__floor_str_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__fmod_inf_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__gamma_neg_int_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__gcd_float_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__isqrt_negative_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__ldexp_overflow_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__log1p_domain_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__log_base1_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__log_zero_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__module.py +1432 -0
- package/ref-monty/crates/monty/test_cases/math__pow_domain_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__sin_inf_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__sqrt_negative_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__tan_inf_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/math__trunc_str_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/method__args_kwargs_unpacking.py +259 -0
- package/ref-monty/crates/monty/test_cases/name_error__unbound_local_func.py +19 -0
- package/ref-monty/crates/monty/test_cases/name_error__unbound_local_module.py +12 -0
- package/ref-monty/crates/monty/test_cases/name_error__undefined_call_chained.py +9 -0
- package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_expr.py +9 -0
- package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_function.py +16 -0
- package/ref-monty/crates/monty/test_cases/name_error__undefined_call_with_args.py +9 -0
- package/ref-monty/crates/monty/test_cases/name_error__undefined_global.py +10 -0
- package/ref-monty/crates/monty/test_cases/namedtuple__missing_attr.py +11 -0
- package/ref-monty/crates/monty/test_cases/namedtuple__ops.py +34 -0
- package/ref-monty/crates/monty/test_cases/nonlocal__error_module_level.py +3 -0
- package/ref-monty/crates/monty/test_cases/nonlocal__ops.py +353 -0
- package/ref-monty/crates/monty/test_cases/os__environ.py +40 -0
- package/ref-monty/crates/monty/test_cases/os__getenv_key_list_error.py +5 -0
- package/ref-monty/crates/monty/test_cases/os__getenv_key_type_error.py +5 -0
- package/ref-monty/crates/monty/test_cases/parse_error__complex.py +3 -0
- package/ref-monty/crates/monty/test_cases/pathlib__import.py +11 -0
- package/ref-monty/crates/monty/test_cases/pathlib__os.py +136 -0
- package/ref-monty/crates/monty/test_cases/pathlib__os_read_error.py +12 -0
- package/ref-monty/crates/monty/test_cases/pathlib__pure.py +81 -0
- package/ref-monty/crates/monty/test_cases/pyobject__cycle_dict_self.py +5 -0
- package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_dict.py +6 -0
- package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_self.py +5 -0
- package/ref-monty/crates/monty/test_cases/pyobject__cycle_multiple_refs.py +6 -0
- package/ref-monty/crates/monty/test_cases/range__error_no_args.py +2 -0
- package/ref-monty/crates/monty/test_cases/range__error_step_zero.py +2 -0
- package/ref-monty/crates/monty/test_cases/range__error_too_many_args.py +2 -0
- package/ref-monty/crates/monty/test_cases/range__getitem_index_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/range__ops.py +236 -0
- package/ref-monty/crates/monty/test_cases/re__basic.py +756 -0
- package/ref-monty/crates/monty/test_cases/re__grouping.py +241 -0
- package/ref-monty/crates/monty/test_cases/re__match.py +148 -0
- package/ref-monty/crates/monty/test_cases/recursion__deep_drop.py +26 -0
- package/ref-monty/crates/monty/test_cases/recursion__deep_eq.py +23 -0
- package/ref-monty/crates/monty/test_cases/recursion__deep_hash.py +46 -0
- package/ref-monty/crates/monty/test_cases/recursion__deep_repr.py +12 -0
- package/ref-monty/crates/monty/test_cases/recursion__function_depth.py +13 -0
- package/ref-monty/crates/monty/test_cases/refcount__cycle_mutual_reference.py +18 -0
- package/ref-monty/crates/monty/test_cases/refcount__cycle_self_reference.py +12 -0
- package/ref-monty/crates/monty/test_cases/refcount__dict_basic.py +5 -0
- package/ref-monty/crates/monty/test_cases/refcount__dict_get.py +5 -0
- package/ref-monty/crates/monty/test_cases/refcount__dict_keys_and.py +14 -0
- package/ref-monty/crates/monty/test_cases/refcount__dict_overwrite.py +6 -0
- package/ref-monty/crates/monty/test_cases/refcount__gather_cleanup.py +16 -0
- package/ref-monty/crates/monty/test_cases/refcount__gather_exception.py +18 -0
- package/ref-monty/crates/monty/test_cases/refcount__gather_nested_cancel.py +25 -0
- package/ref-monty/crates/monty/test_cases/refcount__immediate_skipped.py +4 -0
- package/ref-monty/crates/monty/test_cases/refcount__kwargs_unpacking.py +27 -0
- package/ref-monty/crates/monty/test_cases/refcount__list_append_multiple.py +6 -0
- package/ref-monty/crates/monty/test_cases/refcount__list_append_ref.py +5 -0
- package/ref-monty/crates/monty/test_cases/refcount__list_concat.py +5 -0
- package/ref-monty/crates/monty/test_cases/refcount__list_getitem.py +5 -0
- package/ref-monty/crates/monty/test_cases/refcount__list_iadd.py +5 -0
- package/ref-monty/crates/monty/test_cases/refcount__nested_list.py +4 -0
- package/ref-monty/crates/monty/test_cases/refcount__re_pattern_sub_error_paths.py +37 -0
- package/ref-monty/crates/monty/test_cases/refcount__re_search_match.py +34 -0
- package/ref-monty/crates/monty/test_cases/refcount__re_sub_error_paths.py +31 -0
- package/ref-monty/crates/monty/test_cases/refcount__shared_reference.py +4 -0
- package/ref-monty/crates/monty/test_cases/refcount__single_list.py +3 -0
- package/ref-monty/crates/monty/test_cases/repr__cycle_detection.py +24 -0
- package/ref-monty/crates/monty/test_cases/set__ops.py +191 -0
- package/ref-monty/crates/monty/test_cases/set__review_bugs.py +35 -0
- package/ref-monty/crates/monty/test_cases/set__unpack_type_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/slice__invalid_indices.py +2 -0
- package/ref-monty/crates/monty/test_cases/slice__kwargs.py +9 -0
- package/ref-monty/crates/monty/test_cases/slice__no_args.py +9 -0
- package/ref-monty/crates/monty/test_cases/slice__ops.py +149 -0
- package/ref-monty/crates/monty/test_cases/slice__step_zero.py +9 -0
- package/ref-monty/crates/monty/test_cases/slice__step_zero_bytes.py +9 -0
- package/ref-monty/crates/monty/test_cases/slice__step_zero_range.py +9 -0
- package/ref-monty/crates/monty/test_cases/slice__step_zero_str.py +9 -0
- package/ref-monty/crates/monty/test_cases/slice__step_zero_tuple.py +9 -0
- package/ref-monty/crates/monty/test_cases/slice__too_many_args.py +9 -0
- package/ref-monty/crates/monty/test_cases/str__getitem_index_error.py +10 -0
- package/ref-monty/crates/monty/test_cases/str__index_not_found.py +9 -0
- package/ref-monty/crates/monty/test_cases/str__join_no_args.py +9 -0
- package/ref-monty/crates/monty/test_cases/str__join_non_string.py +9 -0
- package/ref-monty/crates/monty/test_cases/str__join_not_iterable.py +9 -0
- package/ref-monty/crates/monty/test_cases/str__join_too_many_args.py +9 -0
- package/ref-monty/crates/monty/test_cases/str__methods.py +327 -0
- package/ref-monty/crates/monty/test_cases/str__ops.py +162 -0
- package/ref-monty/crates/monty/test_cases/str__partition_empty.py +9 -0
- package/ref-monty/crates/monty/test_cases/str__rsplit_empty_sep.py +9 -0
- package/ref-monty/crates/monty/test_cases/str__split_empty_sep.py +9 -0
- package/ref-monty/crates/monty/test_cases/sys__types.py +7 -0
- package/ref-monty/crates/monty/test_cases/traceback__division_error.py +30 -0
- package/ref-monty/crates/monty/test_cases/traceback__index_error.py +17 -0
- package/ref-monty/crates/monty/test_cases/traceback__insert_as_int.py +10 -0
- package/ref-monty/crates/monty/test_cases/traceback__nested_call.py +29 -0
- package/ref-monty/crates/monty/test_cases/traceback__nonlocal_module_scope.py +10 -0
- package/ref-monty/crates/monty/test_cases/traceback__nonlocal_unbound.py +24 -0
- package/ref-monty/crates/monty/test_cases/traceback__range_as_int.py +9 -0
- package/ref-monty/crates/monty/test_cases/traceback__recursion_error.py +23 -0
- package/ref-monty/crates/monty/test_cases/traceback__set_mutation.py +11 -0
- package/ref-monty/crates/monty/test_cases/traceback__undefined_attr_call.py +16 -0
- package/ref-monty/crates/monty/test_cases/traceback__undefined_call.py +16 -0
- package/ref-monty/crates/monty/test_cases/traceback__undefined_raise.py +16 -0
- package/ref-monty/crates/monty/test_cases/try_except__all.py +472 -0
- package/ref-monty/crates/monty/test_cases/try_except__bare_raise_no_context.py +2 -0
- package/ref-monty/crates/monty/test_cases/try_except__invalid_type.py +5 -0
- package/ref-monty/crates/monty/test_cases/tuple__getitem_out_of_bounds.py +3 -0
- package/ref-monty/crates/monty/test_cases/tuple__index_not_found.py +9 -0
- package/ref-monty/crates/monty/test_cases/tuple__index_start_gt_end.py +10 -0
- package/ref-monty/crates/monty/test_cases/tuple__methods.py +19 -0
- package/ref-monty/crates/monty/test_cases/tuple__ops.py +133 -0
- package/ref-monty/crates/monty/test_cases/tuple__unpack_type_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/type__builtin_attr_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/type__bytes_negative.py +2 -0
- package/ref-monty/crates/monty/test_cases/type__cell_not_builtin.py +9 -0
- package/ref-monty/crates/monty/test_cases/type__exception_attr_error.py +11 -0
- package/ref-monty/crates/monty/test_cases/type__float_conversion_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/type__float_repr_both_quotes.py +9 -0
- package/ref-monty/crates/monty/test_cases/type__float_repr_newline.py +9 -0
- package/ref-monty/crates/monty/test_cases/type__float_repr_single_quote.py +9 -0
- package/ref-monty/crates/monty/test_cases/type__int_conversion_error.py +2 -0
- package/ref-monty/crates/monty/test_cases/type__list_not_iterable.py +2 -0
- package/ref-monty/crates/monty/test_cases/type__non_builtin_name_error.py +9 -0
- package/ref-monty/crates/monty/test_cases/type__ops.py +200 -0
- package/ref-monty/crates/monty/test_cases/type__shadow_exc.py +3 -0
- package/ref-monty/crates/monty/test_cases/type__shadow_int.py +9 -0
- package/ref-monty/crates/monty/test_cases/type__shadow_len.py +3 -0
- package/ref-monty/crates/monty/test_cases/type__tuple_not_iterable.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__int_add_list.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__int_div_str.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__int_floordiv_str.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__int_iadd_str.py +3 -0
- package/ref-monty/crates/monty/test_cases/type_error__int_mod_str.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__int_pow_str.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__int_sub_str.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__list_add_int.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__list_add_str.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__list_iadd_int.py +6 -0
- package/ref-monty/crates/monty/test_cases/type_error__str_add_int.py +2 -0
- package/ref-monty/crates/monty/test_cases/type_error__str_iadd_int.py +3 -0
- package/ref-monty/crates/monty/test_cases/type_error__unary_invert_str.py +3 -0
- package/ref-monty/crates/monty/test_cases/type_error__unary_minus_str.py +4 -0
- package/ref-monty/crates/monty/test_cases/type_error__unary_neg_str.py +3 -0
- package/ref-monty/crates/monty/test_cases/type_error__unary_plus_str.py +4 -0
- package/ref-monty/crates/monty/test_cases/typing__types.py +24 -0
- package/ref-monty/crates/monty/test_cases/unpack__nested.py +48 -0
- package/ref-monty/crates/monty/test_cases/unpack__non_sequence.py +9 -0
- package/ref-monty/crates/monty/test_cases/unpack__not_enough.py +9 -0
- package/ref-monty/crates/monty/test_cases/unpack__ops.py +153 -0
- package/ref-monty/crates/monty/test_cases/unpack__star_not_enough.py +9 -0
- package/ref-monty/crates/monty/test_cases/unpack__too_many.py +9 -0
- package/ref-monty/crates/monty/test_cases/version__cpython.py +4 -0
- package/ref-monty/crates/monty/test_cases/walrus__all.py +178 -0
- package/ref-monty/crates/monty/test_cases/while__all.py +206 -0
- package/ref-monty/crates/monty/tests/asyncio.rs +764 -0
- package/ref-monty/crates/monty/tests/binary_serde.rs +185 -0
- package/ref-monty/crates/monty/tests/bytecode_limits.rs +248 -0
- package/ref-monty/crates/monty/tests/datatest_runner.rs +2029 -0
- package/ref-monty/crates/monty/tests/inputs.rs +420 -0
- package/ref-monty/crates/monty/tests/json_serde.rs +250 -0
- package/ref-monty/crates/monty/tests/main.rs +71 -0
- package/ref-monty/crates/monty/tests/math_module.rs +114 -0
- package/ref-monty/crates/monty/tests/name_lookup.rs +482 -0
- package/ref-monty/crates/monty/tests/os_tests.rs +459 -0
- package/ref-monty/crates/monty/tests/parse_errors.rs +441 -0
- package/ref-monty/crates/monty/tests/print_writer.rs +238 -0
- package/ref-monty/crates/monty/tests/py_object.rs +121 -0
- package/ref-monty/crates/monty/tests/regex.rs +90 -0
- package/ref-monty/crates/monty/tests/repl.rs +344 -0
- package/ref-monty/crates/monty/tests/resource_limits.rs +1826 -0
- package/ref-monty/crates/monty/tests/try_from.rs +167 -0
- package/ref-monty/crates/monty-cli/Cargo.toml +25 -0
- package/ref-monty/crates/monty-cli/src/main.rs +541 -0
- package/ref-monty/crates/monty-js/.cargo/config.toml +2 -0
- package/ref-monty/crates/monty-js/.prettierignore +8 -0
- package/ref-monty/crates/monty-js/Cargo.toml +32 -0
- package/ref-monty/crates/monty-js/README.md +207 -0
- package/ref-monty/crates/monty-js/__test__/async.spec.ts +350 -0
- package/ref-monty/crates/monty-js/__test__/basic.spec.ts +114 -0
- package/ref-monty/crates/monty-js/__test__/exceptions.spec.ts +427 -0
- package/ref-monty/crates/monty-js/__test__/external.spec.ts +354 -0
- package/ref-monty/crates/monty-js/__test__/inputs.spec.ts +143 -0
- package/ref-monty/crates/monty-js/__test__/limits.spec.ts +162 -0
- package/ref-monty/crates/monty-js/__test__/package.json +3 -0
- package/ref-monty/crates/monty-js/__test__/print.spec.ts +229 -0
- package/ref-monty/crates/monty-js/__test__/repl.spec.ts +34 -0
- package/ref-monty/crates/monty-js/__test__/serialize.spec.ts +205 -0
- package/ref-monty/crates/monty-js/__test__/start.spec.ts +443 -0
- package/ref-monty/crates/monty-js/__test__/type_check.spec.ts +147 -0
- package/ref-monty/crates/monty-js/__test__/types.spec.ts +319 -0
- package/ref-monty/crates/monty-js/build.rs +61 -0
- package/ref-monty/crates/monty-js/index-header.d.ts +3 -0
- package/ref-monty/crates/monty-js/package-lock.json +4694 -0
- package/ref-monty/crates/monty-js/package.json +100 -0
- package/ref-monty/crates/monty-js/scripts/smoke-test.sh +69 -0
- package/ref-monty/crates/monty-js/smoke-test/package.json +17 -0
- package/ref-monty/crates/monty-js/smoke-test/test.ts +171 -0
- package/ref-monty/crates/monty-js/smoke-test/tsconfig.json +11 -0
- package/ref-monty/crates/monty-js/src/convert.rs +648 -0
- package/ref-monty/crates/monty-js/src/exceptions.rs +293 -0
- package/ref-monty/crates/monty-js/src/lib.rs +41 -0
- package/ref-monty/crates/monty-js/src/limits.rs +53 -0
- package/ref-monty/crates/monty-js/src/monty_cls.rs +1407 -0
- package/ref-monty/crates/monty-js/tsconfig.json +17 -0
- package/ref-monty/crates/monty-js/wrapper.ts +701 -0
- package/ref-monty/crates/monty-python/Cargo.toml +38 -0
- package/ref-monty/crates/monty-python/README.md +134 -0
- package/ref-monty/crates/monty-python/build.rs +4 -0
- package/ref-monty/crates/monty-python/example.py +40 -0
- package/ref-monty/crates/monty-python/exercise.py +46 -0
- package/ref-monty/crates/monty-python/pyproject.toml +57 -0
- package/ref-monty/crates/monty-python/python/pydantic_monty/__init__.py +281 -0
- package/ref-monty/crates/monty-python/python/pydantic_monty/_monty.pyi +677 -0
- package/ref-monty/crates/monty-python/python/pydantic_monty/os_access.py +933 -0
- package/ref-monty/crates/monty-python/python/pydantic_monty/py.typed +0 -0
- package/ref-monty/crates/monty-python/src/convert.rs +273 -0
- package/ref-monty/crates/monty-python/src/dataclass.rs +461 -0
- package/ref-monty/crates/monty-python/src/exceptions.rs +557 -0
- package/ref-monty/crates/monty-python/src/external.rs +165 -0
- package/ref-monty/crates/monty-python/src/lib.rs +77 -0
- package/ref-monty/crates/monty-python/src/limits.rs +142 -0
- package/ref-monty/crates/monty-python/src/monty_cls.rs +1650 -0
- package/ref-monty/crates/monty-python/src/repl.rs +470 -0
- package/ref-monty/crates/monty-python/src/serialization.rs +761 -0
- package/ref-monty/crates/monty-python/tests/test_async.py +1201 -0
- package/ref-monty/crates/monty-python/tests/test_basic.py +66 -0
- package/ref-monty/crates/monty-python/tests/test_dataclasses.py +971 -0
- package/ref-monty/crates/monty-python/tests/test_exceptions.py +361 -0
- package/ref-monty/crates/monty-python/tests/test_external.py +367 -0
- package/ref-monty/crates/monty-python/tests/test_inputs.py +126 -0
- package/ref-monty/crates/monty-python/tests/test_limits.py +257 -0
- package/ref-monty/crates/monty-python/tests/test_os_access.py +1286 -0
- package/ref-monty/crates/monty-python/tests/test_os_access_compat.py +731 -0
- package/ref-monty/crates/monty-python/tests/test_os_access_raw.py +483 -0
- package/ref-monty/crates/monty-python/tests/test_os_calls.py +819 -0
- package/ref-monty/crates/monty-python/tests/test_print.py +208 -0
- package/ref-monty/crates/monty-python/tests/test_re.py +170 -0
- package/ref-monty/crates/monty-python/tests/test_readme_examples.py +20 -0
- package/ref-monty/crates/monty-python/tests/test_repl.py +749 -0
- package/ref-monty/crates/monty-python/tests/test_serialize.py +284 -0
- package/ref-monty/crates/monty-python/tests/test_start.py +346 -0
- package/ref-monty/crates/monty-python/tests/test_threading.py +163 -0
- package/ref-monty/crates/monty-python/tests/test_type_check.py +344 -0
- package/ref-monty/crates/monty-python/tests/test_types.py +553 -0
- package/ref-monty/crates/monty-type-checking/Cargo.toml +32 -0
- package/ref-monty/crates/monty-type-checking/src/db.rs +116 -0
- package/ref-monty/crates/monty-type-checking/src/lib.rs +4 -0
- package/ref-monty/crates/monty-type-checking/src/type_check.rs +280 -0
- package/ref-monty/crates/monty-type-checking/tests/bad_types.py +109 -0
- package/ref-monty/crates/monty-type-checking/tests/bad_types_output.txt +21 -0
- package/ref-monty/crates/monty-type-checking/tests/good_types.py +475 -0
- package/ref-monty/crates/monty-type-checking/tests/main.rs +205 -0
- package/ref-monty/crates/monty-type-checking/tests/reveal_types.py +56 -0
- package/ref-monty/crates/monty-type-checking/tests/reveal_types_output.txt +41 -0
- package/ref-monty/crates/monty-typeshed/Cargo.toml +29 -0
- package/ref-monty/crates/monty-typeshed/README.md +11 -0
- package/ref-monty/crates/monty-typeshed/build.rs +101 -0
- package/ref-monty/crates/monty-typeshed/custom/README.md +1 -0
- package/ref-monty/crates/monty-typeshed/custom/asyncio.pyi +138 -0
- package/ref-monty/crates/monty-typeshed/custom/os.pyi +87 -0
- package/ref-monty/crates/monty-typeshed/custom/sys.pyi +33 -0
- package/ref-monty/crates/monty-typeshed/src/lib.rs +56 -0
- package/ref-monty/crates/monty-typeshed/update.py +321 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/source_commit.txt +1 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/VERSIONS +20 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi +105 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi +394 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi +138 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi +1434 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi +527 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/abc.pyi +2 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/dataclasses.pyi +502 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/enum.pyi +376 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/math.pyi +149 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/os.pyi +87 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/__init__.pyi +395 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/types.pyi +8 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/re.pyi +337 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/sys.pyi +33 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/types.pyi +741 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing.pyi +1217 -0
- package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing_extensions.pyi +716 -0
- package/ref-monty/docs/usage-guide.md +117 -0
- package/ref-monty/examples/README.md +3 -0
- package/ref-monty/examples/expense_analysis/README.md +3 -0
- package/ref-monty/examples/expense_analysis/data.py +124 -0
- package/ref-monty/examples/expense_analysis/main.py +115 -0
- package/ref-monty/examples/sql_playground/README.md +20 -0
- package/ref-monty/examples/sql_playground/external_functions.py +129 -0
- package/ref-monty/examples/sql_playground/main.py +81 -0
- package/ref-monty/examples/sql_playground/sandbox_code.py +82 -0
- package/ref-monty/examples/sql_playground/type_stubs.pyi +14 -0
- package/ref-monty/examples/web_scraper/README.md +15 -0
- package/ref-monty/examples/web_scraper/browser.py +56 -0
- package/ref-monty/examples/web_scraper/example_code.py +59 -0
- package/ref-monty/examples/web_scraper/external_functions.py +324 -0
- package/ref-monty/examples/web_scraper/main.py +193 -0
- package/ref-monty/examples/web_scraper/sub_agent.py +79 -0
- package/ref-monty/monty-npm.md +235 -0
- package/ref-monty/pyproject.toml +162 -0
- package/ref-monty/scripts/check_imports.py +91 -0
- package/ref-monty/scripts/codecov_diff.py +412 -0
- package/ref-monty/scripts/complete_tests.py +146 -0
- package/ref-monty/scripts/flamegraph_to_text.py +208 -0
- package/ref-monty/scripts/iter_test_methods.py +540 -0
- package/ref-monty/scripts/run_traceback.py +180 -0
- package/ref-monty/scripts/startup_performance.py +130 -0
- package/ref-monty/uv.lock +1779 -0
- package/temp_resend_cli/repo/.github/scripts/pr-title-check.js +34 -0
- package/temp_resend_cli/repo/.github/workflows/ci.yml +67 -0
- package/temp_resend_cli/repo/.github/workflows/post-release.yml +51 -0
- package/temp_resend_cli/repo/.github/workflows/pr-title-check.yml +13 -0
- package/temp_resend_cli/repo/.github/workflows/release.yml +175 -0
- package/temp_resend_cli/repo/.github/workflows/test-install-unix.yml +34 -0
- package/temp_resend_cli/repo/.github/workflows/test-install-windows.yml +48 -0
- package/temp_resend_cli/repo/CHANGELOG.md +31 -0
- package/temp_resend_cli/repo/LICENSE +21 -0
- package/temp_resend_cli/repo/README.md +450 -0
- package/temp_resend_cli/repo/biome.json +36 -0
- package/temp_resend_cli/repo/install.ps1 +141 -0
- package/temp_resend_cli/repo/install.sh +301 -0
- package/temp_resend_cli/repo/package.json +61 -0
- package/temp_resend_cli/repo/pnpm-lock.yaml +2439 -0
- package/temp_resend_cli/repo/renovate.json +4 -0
- package/temp_resend_cli/repo/src/cli.ts +98 -0
- package/temp_resend_cli/repo/src/commands/api-keys/create.ts +114 -0
- package/temp_resend_cli/repo/src/commands/api-keys/delete.ts +47 -0
- package/temp_resend_cli/repo/src/commands/api-keys/index.ts +26 -0
- package/temp_resend_cli/repo/src/commands/api-keys/list.ts +35 -0
- package/temp_resend_cli/repo/src/commands/api-keys/utils.ts +8 -0
- package/temp_resend_cli/repo/src/commands/auth/index.ts +20 -0
- package/temp_resend_cli/repo/src/commands/auth/login.ts +234 -0
- package/temp_resend_cli/repo/src/commands/auth/logout.ts +105 -0
- package/temp_resend_cli/repo/src/commands/broadcasts/create.ts +196 -0
- package/temp_resend_cli/repo/src/commands/broadcasts/delete.ts +46 -0
- package/temp_resend_cli/repo/src/commands/broadcasts/get.ts +59 -0
- package/temp_resend_cli/repo/src/commands/broadcasts/index.ts +43 -0
- package/temp_resend_cli/repo/src/commands/broadcasts/list.ts +60 -0
- package/temp_resend_cli/repo/src/commands/broadcasts/send.ts +56 -0
- package/temp_resend_cli/repo/src/commands/broadcasts/update.ts +95 -0
- package/temp_resend_cli/repo/src/commands/broadcasts/utils.ts +35 -0
- package/temp_resend_cli/repo/src/commands/contact-properties/create.ts +118 -0
- package/temp_resend_cli/repo/src/commands/contact-properties/delete.ts +48 -0
- package/temp_resend_cli/repo/src/commands/contact-properties/get.ts +46 -0
- package/temp_resend_cli/repo/src/commands/contact-properties/index.ts +48 -0
- package/temp_resend_cli/repo/src/commands/contact-properties/list.ts +68 -0
- package/temp_resend_cli/repo/src/commands/contact-properties/update.ts +88 -0
- package/temp_resend_cli/repo/src/commands/contact-properties/utils.ts +17 -0
- package/temp_resend_cli/repo/src/commands/contacts/add-segment.ts +78 -0
- package/temp_resend_cli/repo/src/commands/contacts/create.ts +122 -0
- package/temp_resend_cli/repo/src/commands/contacts/delete.ts +49 -0
- package/temp_resend_cli/repo/src/commands/contacts/get.ts +53 -0
- package/temp_resend_cli/repo/src/commands/contacts/index.ts +58 -0
- package/temp_resend_cli/repo/src/commands/contacts/list.ts +57 -0
- package/temp_resend_cli/repo/src/commands/contacts/remove-segment.ts +48 -0
- package/temp_resend_cli/repo/src/commands/contacts/segments.ts +39 -0
- package/temp_resend_cli/repo/src/commands/contacts/topics.ts +45 -0
- package/temp_resend_cli/repo/src/commands/contacts/update-topics.ts +90 -0
- package/temp_resend_cli/repo/src/commands/contacts/update.ts +77 -0
- package/temp_resend_cli/repo/src/commands/contacts/utils.ts +119 -0
- package/temp_resend_cli/repo/src/commands/doctor.ts +216 -0
- package/temp_resend_cli/repo/src/commands/domains/create.ts +83 -0
- package/temp_resend_cli/repo/src/commands/domains/delete.ts +42 -0
- package/temp_resend_cli/repo/src/commands/domains/get.ts +47 -0
- package/temp_resend_cli/repo/src/commands/domains/index.ts +35 -0
- package/temp_resend_cli/repo/src/commands/domains/list.ts +53 -0
- package/temp_resend_cli/repo/src/commands/domains/update.ts +75 -0
- package/temp_resend_cli/repo/src/commands/domains/utils.ts +44 -0
- package/temp_resend_cli/repo/src/commands/domains/verify.ts +38 -0
- package/temp_resend_cli/repo/src/commands/emails/batch.ts +140 -0
- package/temp_resend_cli/repo/src/commands/emails/get.ts +44 -0
- package/temp_resend_cli/repo/src/commands/emails/index.ts +30 -0
- package/temp_resend_cli/repo/src/commands/emails/list.ts +84 -0
- package/temp_resend_cli/repo/src/commands/emails/receiving/attachment.ts +55 -0
- package/temp_resend_cli/repo/src/commands/emails/receiving/attachments.ts +68 -0
- package/temp_resend_cli/repo/src/commands/emails/receiving/get.ts +58 -0
- package/temp_resend_cli/repo/src/commands/emails/receiving/index.ts +28 -0
- package/temp_resend_cli/repo/src/commands/emails/receiving/list.ts +59 -0
- package/temp_resend_cli/repo/src/commands/emails/receiving/utils.ts +38 -0
- package/temp_resend_cli/repo/src/commands/emails/send.ts +189 -0
- package/temp_resend_cli/repo/src/commands/open.ts +27 -0
- package/temp_resend_cli/repo/src/commands/segments/create.ts +50 -0
- package/temp_resend_cli/repo/src/commands/segments/delete.ts +47 -0
- package/temp_resend_cli/repo/src/commands/segments/get.ts +38 -0
- package/temp_resend_cli/repo/src/commands/segments/index.ts +36 -0
- package/temp_resend_cli/repo/src/commands/segments/list.ts +58 -0
- package/temp_resend_cli/repo/src/commands/segments/utils.ts +7 -0
- package/temp_resend_cli/repo/src/commands/teams/index.ts +10 -0
- package/temp_resend_cli/repo/src/commands/teams/list.ts +35 -0
- package/temp_resend_cli/repo/src/commands/teams/remove.ts +86 -0
- package/temp_resend_cli/repo/src/commands/teams/switch.ts +76 -0
- package/temp_resend_cli/repo/src/commands/topics/create.ts +73 -0
- package/temp_resend_cli/repo/src/commands/topics/delete.ts +47 -0
- package/temp_resend_cli/repo/src/commands/topics/get.ts +42 -0
- package/temp_resend_cli/repo/src/commands/topics/index.ts +42 -0
- package/temp_resend_cli/repo/src/commands/topics/list.ts +34 -0
- package/temp_resend_cli/repo/src/commands/topics/update.ts +59 -0
- package/temp_resend_cli/repo/src/commands/topics/utils.ts +16 -0
- package/temp_resend_cli/repo/src/commands/webhooks/create.ts +128 -0
- package/temp_resend_cli/repo/src/commands/webhooks/delete.ts +49 -0
- package/temp_resend_cli/repo/src/commands/webhooks/get.ts +42 -0
- package/temp_resend_cli/repo/src/commands/webhooks/index.ts +42 -0
- package/temp_resend_cli/repo/src/commands/webhooks/list.ts +55 -0
- package/temp_resend_cli/repo/src/commands/webhooks/listen.ts +379 -0
- package/temp_resend_cli/repo/src/commands/webhooks/update.ts +83 -0
- package/temp_resend_cli/repo/src/commands/webhooks/utils.ts +36 -0
- package/temp_resend_cli/repo/src/commands/whoami.ts +71 -0
- package/temp_resend_cli/repo/src/lib/actions.ts +157 -0
- package/temp_resend_cli/repo/src/lib/client.ts +37 -0
- package/temp_resend_cli/repo/src/lib/config.ts +217 -0
- package/temp_resend_cli/repo/src/lib/files.ts +15 -0
- package/temp_resend_cli/repo/src/lib/help-text.ts +38 -0
- package/temp_resend_cli/repo/src/lib/output.ts +56 -0
- package/temp_resend_cli/repo/src/lib/pagination.ts +36 -0
- package/temp_resend_cli/repo/src/lib/prompts.ts +149 -0
- package/temp_resend_cli/repo/src/lib/spinner.ts +100 -0
- package/temp_resend_cli/repo/src/lib/table.ts +57 -0
- package/temp_resend_cli/repo/src/lib/tty.ts +28 -0
- package/temp_resend_cli/repo/src/lib/update-check.ts +169 -0
- package/temp_resend_cli/repo/src/lib/version.ts +4 -0
- package/temp_resend_cli/repo/tests/commands/api-keys/create.test.ts +196 -0
- package/temp_resend_cli/repo/tests/commands/api-keys/delete.test.ts +157 -0
- package/temp_resend_cli/repo/tests/commands/api-keys/list.test.ts +134 -0
- package/temp_resend_cli/repo/tests/commands/auth/login.test.ts +153 -0
- package/temp_resend_cli/repo/tests/commands/auth/logout.test.ts +153 -0
- package/temp_resend_cli/repo/tests/commands/broadcasts/create.test.ts +454 -0
- package/temp_resend_cli/repo/tests/commands/broadcasts/delete.test.ts +183 -0
- package/temp_resend_cli/repo/tests/commands/broadcasts/get.test.ts +147 -0
- package/temp_resend_cli/repo/tests/commands/broadcasts/list.test.ts +199 -0
- package/temp_resend_cli/repo/tests/commands/broadcasts/send.test.ts +162 -0
- package/temp_resend_cli/repo/tests/commands/broadcasts/update.test.ts +288 -0
- package/temp_resend_cli/repo/tests/commands/contact-properties/create.test.ts +251 -0
- package/temp_resend_cli/repo/tests/commands/contact-properties/delete.test.ts +184 -0
- package/temp_resend_cli/repo/tests/commands/contact-properties/get.test.ts +145 -0
- package/temp_resend_cli/repo/tests/commands/contact-properties/list.test.ts +181 -0
- package/temp_resend_cli/repo/tests/commands/contact-properties/update.test.ts +217 -0
- package/temp_resend_cli/repo/tests/commands/contacts/add-segment.test.ts +189 -0
- package/temp_resend_cli/repo/tests/commands/contacts/create.test.ts +271 -0
- package/temp_resend_cli/repo/tests/commands/contacts/delete.test.ts +193 -0
- package/temp_resend_cli/repo/tests/commands/contacts/get.test.ts +149 -0
- package/temp_resend_cli/repo/tests/commands/contacts/list.test.ts +176 -0
- package/temp_resend_cli/repo/tests/commands/contacts/remove-segment.test.ts +167 -0
- package/temp_resend_cli/repo/tests/commands/contacts/segments.test.ts +168 -0
- package/temp_resend_cli/repo/tests/commands/contacts/topics.test.ts +164 -0
- package/temp_resend_cli/repo/tests/commands/contacts/update-topics.test.ts +248 -0
- package/temp_resend_cli/repo/tests/commands/contacts/update.test.ts +206 -0
- package/temp_resend_cli/repo/tests/commands/doctor.test.ts +164 -0
- package/temp_resend_cli/repo/tests/commands/domains/create.test.ts +193 -0
- package/temp_resend_cli/repo/tests/commands/domains/delete.test.ts +157 -0
- package/temp_resend_cli/repo/tests/commands/domains/get.test.ts +138 -0
- package/temp_resend_cli/repo/tests/commands/domains/list.test.ts +165 -0
- package/temp_resend_cli/repo/tests/commands/domains/update.test.ts +224 -0
- package/temp_resend_cli/repo/tests/commands/domains/verify.test.ts +118 -0
- package/temp_resend_cli/repo/tests/commands/emails/batch.test.ts +324 -0
- package/temp_resend_cli/repo/tests/commands/emails/get.test.ts +132 -0
- package/temp_resend_cli/repo/tests/commands/emails/receiving/attachment.test.ts +141 -0
- package/temp_resend_cli/repo/tests/commands/emails/receiving/attachments.test.ts +169 -0
- package/temp_resend_cli/repo/tests/commands/emails/receiving/get.test.ts +141 -0
- package/temp_resend_cli/repo/tests/commands/emails/receiving/list.test.ts +182 -0
- package/temp_resend_cli/repo/tests/commands/emails/send.test.ts +312 -0
- package/temp_resend_cli/repo/tests/commands/segments/create.test.ts +164 -0
- package/temp_resend_cli/repo/tests/commands/segments/delete.test.ts +183 -0
- package/temp_resend_cli/repo/tests/commands/segments/get.test.ts +138 -0
- package/temp_resend_cli/repo/tests/commands/segments/list.test.ts +174 -0
- package/temp_resend_cli/repo/tests/commands/teams/list.test.ts +62 -0
- package/temp_resend_cli/repo/tests/commands/teams/remove.test.ts +110 -0
- package/temp_resend_cli/repo/tests/commands/teams/switch.test.ts +103 -0
- package/temp_resend_cli/repo/tests/commands/topics/create.test.ts +192 -0
- package/temp_resend_cli/repo/tests/commands/topics/delete.test.ts +157 -0
- package/temp_resend_cli/repo/tests/commands/topics/get.test.ts +126 -0
- package/temp_resend_cli/repo/tests/commands/topics/list.test.ts +125 -0
- package/temp_resend_cli/repo/tests/commands/topics/update.test.ts +178 -0
- package/temp_resend_cli/repo/tests/commands/webhooks/create.test.ts +225 -0
- package/temp_resend_cli/repo/tests/commands/webhooks/delete.test.ts +157 -0
- package/temp_resend_cli/repo/tests/commands/webhooks/get.test.ts +126 -0
- package/temp_resend_cli/repo/tests/commands/webhooks/list.test.ts +178 -0
- package/temp_resend_cli/repo/tests/commands/webhooks/update.test.ts +207 -0
- package/temp_resend_cli/repo/tests/commands/whoami.test.ts +98 -0
- package/temp_resend_cli/repo/tests/e2e/smoke.test.ts +93 -0
- package/temp_resend_cli/repo/tests/helpers.ts +86 -0
- package/temp_resend_cli/repo/tests/lib/client.test.ts +71 -0
- package/temp_resend_cli/repo/tests/lib/config.test.ts +451 -0
- package/temp_resend_cli/repo/tests/lib/files.test.ts +73 -0
- package/temp_resend_cli/repo/tests/lib/help-text.test.ts +97 -0
- package/temp_resend_cli/repo/tests/lib/output.test.ts +136 -0
- package/temp_resend_cli/repo/tests/lib/prompts.test.ts +185 -0
- package/temp_resend_cli/repo/tests/lib/spinner.test.ts +166 -0
- package/temp_resend_cli/repo/tests/lib/table.test.ts +63 -0
- package/temp_resend_cli/repo/tests/lib/tty.test.ts +89 -0
- package/temp_resend_cli/repo/tests/lib/update-check.test.ts +179 -0
- package/temp_resend_cli/repo/tsconfig.json +14 -0
- package/temp_resend_cli/repo/vitest.config.e2e.ts +8 -0
- package/temp_resend_cli/repo/vitest.config.ts +10 -0
- package/tests/test-mcp-browser-use-smoke.sh +28 -56
- package/tests/test-monty-smoke.sh +32 -0
- package/tests/test-resend-smoke.sh +36 -0
|
@@ -0,0 +1,929 @@
|
|
|
1
|
+
use std::fmt::Write;
|
|
2
|
+
|
|
3
|
+
use ahash::AHashSet;
|
|
4
|
+
use itertools::Itertools;
|
|
5
|
+
use smallvec::SmallVec;
|
|
6
|
+
|
|
7
|
+
use super::{MontyIter, PyTrait};
|
|
8
|
+
use crate::{
|
|
9
|
+
args::ArgValues,
|
|
10
|
+
bytecode::{CallResult, VM},
|
|
11
|
+
defer_drop, defer_drop_mut,
|
|
12
|
+
exception_private::{ExcType, RunError, RunResult},
|
|
13
|
+
heap::{DropWithHeap, Heap, HeapData, HeapGuard, HeapId},
|
|
14
|
+
intern::StaticStrings,
|
|
15
|
+
resource::{ResourceError, ResourceTracker},
|
|
16
|
+
sorting::{apply_permutation, sort_indices},
|
|
17
|
+
types::Type,
|
|
18
|
+
value::{EitherStr, Value},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/// Python list type, wrapping a Vec of Values.
|
|
22
|
+
///
|
|
23
|
+
/// This type provides Python list semantics including dynamic growth,
|
|
24
|
+
/// reference counting for heap values, and standard list methods.
|
|
25
|
+
///
|
|
26
|
+
/// # Implemented Methods
|
|
27
|
+
/// - `append(item)` - Add item to end
|
|
28
|
+
/// - `insert(index, item)` - Insert item at index
|
|
29
|
+
/// - `pop([index])` - Remove and return item (default: last)
|
|
30
|
+
/// - `remove(value)` - Remove first occurrence of value
|
|
31
|
+
/// - `clear()` - Remove all items
|
|
32
|
+
/// - `copy()` - Shallow copy
|
|
33
|
+
/// - `extend(iterable)` - Append items from iterable
|
|
34
|
+
/// - `index(value[, start[, end]])` - Find first index of value
|
|
35
|
+
/// - `count(value)` - Count occurrences
|
|
36
|
+
/// - `reverse()` - Reverse in place
|
|
37
|
+
/// - `sort([key][, reverse])` - Sort in place
|
|
38
|
+
///
|
|
39
|
+
/// Note: `sort(key=...)` supports builtin key functions (len, abs, etc.)
|
|
40
|
+
/// but not user-defined functions. This is handled at VM level for access
|
|
41
|
+
/// to function calling machinery.
|
|
42
|
+
///
|
|
43
|
+
/// All list methods from Python's builtins are implemented.
|
|
44
|
+
///
|
|
45
|
+
/// # Reference Counting
|
|
46
|
+
/// When values are added to the list (via append, insert, etc.), their
|
|
47
|
+
/// reference counts are incremented if they are heap-allocated (Ref variants).
|
|
48
|
+
/// This ensures values remain valid while referenced by the list.
|
|
49
|
+
///
|
|
50
|
+
/// # GC Optimization
|
|
51
|
+
/// The `contains_refs` flag tracks whether the list contains any `Value::Ref` items.
|
|
52
|
+
/// This allows `collect_child_ids` and `py_dec_ref_ids` to skip iteration when the
|
|
53
|
+
/// list contains only primitive values (ints, bools, None, etc.), significantly
|
|
54
|
+
/// improving GC performance for lists of primitives.
|
|
55
|
+
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
|
|
56
|
+
pub(crate) struct List {
|
|
57
|
+
items: Vec<Value>,
|
|
58
|
+
/// True if any item in the list is a `Value::Ref`. Used to skip iteration
|
|
59
|
+
/// in `collect_child_ids` and `py_dec_ref_ids` when no refs are present.
|
|
60
|
+
contains_refs: bool,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
impl List {
|
|
64
|
+
/// Creates a new list from a vector of values.
|
|
65
|
+
///
|
|
66
|
+
/// Automatically computes the `contains_refs` flag by checking if any value
|
|
67
|
+
/// is a `Value::Ref`.
|
|
68
|
+
///
|
|
69
|
+
/// Note: This does NOT increment reference counts - the caller must
|
|
70
|
+
/// ensure refcounts are properly managed.
|
|
71
|
+
#[must_use]
|
|
72
|
+
pub fn new(vec: Vec<Value>) -> Self {
|
|
73
|
+
let contains_refs = vec.iter().any(|v| matches!(v, Value::Ref(_)));
|
|
74
|
+
Self {
|
|
75
|
+
items: vec,
|
|
76
|
+
contains_refs,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Returns a reference to the underlying vector.
|
|
81
|
+
#[must_use]
|
|
82
|
+
pub fn as_slice(&self) -> &[Value] {
|
|
83
|
+
&self.items
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// Returns a mutable reference to the underlying vector.
|
|
87
|
+
///
|
|
88
|
+
/// # Safety Considerations
|
|
89
|
+
/// Be careful when mutating the vector directly - you must manually
|
|
90
|
+
/// manage reference counts for any heap values you add or remove.
|
|
91
|
+
/// The `contains_refs` flag is NOT automatically updated by direct
|
|
92
|
+
/// vector mutations. Prefer using `append()` or `insert()` instead.
|
|
93
|
+
pub fn as_vec_mut(&mut self) -> &mut Vec<Value> {
|
|
94
|
+
&mut self.items
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// Returns the number of elements in the list.
|
|
98
|
+
#[must_use]
|
|
99
|
+
pub fn len(&self) -> usize {
|
|
100
|
+
self.items.len()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/// Returns whether the list contains any heap references.
|
|
104
|
+
///
|
|
105
|
+
/// When false, `collect_child_ids` and `py_dec_ref_ids` can skip iteration.
|
|
106
|
+
#[inline]
|
|
107
|
+
#[must_use]
|
|
108
|
+
pub fn contains_refs(&self) -> bool {
|
|
109
|
+
self.contains_refs
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/// Marks that the list contains heap references.
|
|
113
|
+
///
|
|
114
|
+
/// This should be called when directly mutating the list's items vector
|
|
115
|
+
/// (via `as_vec_mut()`) with values that include `Value::Ref` variants.
|
|
116
|
+
#[inline]
|
|
117
|
+
pub fn set_contains_refs(&mut self) {
|
|
118
|
+
self.contains_refs = true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// Appends an element to the end of the list.
|
|
122
|
+
///
|
|
123
|
+
/// The caller transfers ownership of `item` to the list. The item's refcount
|
|
124
|
+
/// is NOT incremented here - the caller is responsible for ensuring the refcount
|
|
125
|
+
/// was already incremented (e.g., via `clone_with_heap` or `evaluate_use`).
|
|
126
|
+
///
|
|
127
|
+
/// Returns `Value::None`, matching Python's behavior where `list.append()` returns None.
|
|
128
|
+
pub fn append(&mut self, heap: &mut Heap<impl ResourceTracker>, item: Value) {
|
|
129
|
+
// Track if we're adding a reference and mark potential cycle
|
|
130
|
+
if matches!(item, Value::Ref(_)) {
|
|
131
|
+
self.contains_refs = true;
|
|
132
|
+
heap.mark_potential_cycle();
|
|
133
|
+
}
|
|
134
|
+
// Ownership transfer - refcount was already handled by caller
|
|
135
|
+
self.items.push(item);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/// Inserts an element at the specified index.
|
|
139
|
+
///
|
|
140
|
+
/// The caller transfers ownership of `item` to the list. The item's refcount
|
|
141
|
+
/// is NOT incremented here - the caller is responsible for ensuring the refcount
|
|
142
|
+
/// was already incremented.
|
|
143
|
+
///
|
|
144
|
+
/// # Arguments
|
|
145
|
+
/// * `index` - The position to insert at (0-based). If index >= len(),
|
|
146
|
+
/// the item is appended to the end (matching Python semantics).
|
|
147
|
+
///
|
|
148
|
+
/// Returns `Value::None`, matching Python's behavior where `list.insert()` returns None.
|
|
149
|
+
pub fn insert(&mut self, heap: &mut Heap<impl ResourceTracker>, index: usize, item: Value) {
|
|
150
|
+
// Track if we're adding a reference and mark potential cycle
|
|
151
|
+
if matches!(item, Value::Ref(_)) {
|
|
152
|
+
self.contains_refs = true;
|
|
153
|
+
heap.mark_potential_cycle();
|
|
154
|
+
}
|
|
155
|
+
// Ownership transfer - refcount was already handled by caller
|
|
156
|
+
// Python's insert() appends if index is out of bounds
|
|
157
|
+
if index >= self.items.len() {
|
|
158
|
+
self.items.push(item);
|
|
159
|
+
} else {
|
|
160
|
+
self.items.insert(index, item);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/// Creates a list from the `list()` constructor call.
|
|
165
|
+
///
|
|
166
|
+
/// - `list()` with no args returns an empty list
|
|
167
|
+
/// - `list(iterable)` creates a list from any iterable (list, tuple, range, str, bytes, dict)
|
|
168
|
+
pub fn init(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
|
|
169
|
+
let value = args.get_zero_one_arg("list", vm.heap)?;
|
|
170
|
+
match value {
|
|
171
|
+
None => {
|
|
172
|
+
let heap_id = vm.heap.allocate(HeapData::List(Self::new(Vec::new())))?;
|
|
173
|
+
Ok(Value::Ref(heap_id))
|
|
174
|
+
}
|
|
175
|
+
Some(v) => {
|
|
176
|
+
let items = MontyIter::new(v, vm)?.collect(vm)?;
|
|
177
|
+
let heap_id = vm.heap.allocate(HeapData::List(Self::new(items)))?;
|
|
178
|
+
Ok(Value::Ref(heap_id))
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// Handles slice-based indexing for lists.
|
|
184
|
+
///
|
|
185
|
+
/// Returns a new list containing the selected elements.
|
|
186
|
+
fn getitem_slice(&self, slice: &crate::types::Slice, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
|
|
187
|
+
let (start, stop, step) = slice
|
|
188
|
+
.indices(self.items.len())
|
|
189
|
+
.map_err(|()| ExcType::value_error_slice_step_zero())?;
|
|
190
|
+
|
|
191
|
+
let items = get_slice_items(&self.items, start, stop, step, heap)?;
|
|
192
|
+
let heap_id = heap.allocate(HeapData::List(Self::new(items)))?;
|
|
193
|
+
Ok(Value::Ref(heap_id))
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
impl From<List> for Vec<Value> {
|
|
198
|
+
fn from(list: List) -> Self {
|
|
199
|
+
list.items
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
impl PyTrait for List {
|
|
204
|
+
fn py_type(&self, _heap: &Heap<impl ResourceTracker>) -> Type {
|
|
205
|
+
Type::List
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
fn py_estimate_size(&self) -> usize {
|
|
209
|
+
std::mem::size_of::<Self>() + self.items.len() * std::mem::size_of::<Value>()
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
fn py_len(&self, _vm: &VM<'_, '_, impl ResourceTracker>) -> Option<usize> {
|
|
213
|
+
Some(self.items.len())
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
fn py_getitem(&self, key: &Value, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
|
|
217
|
+
let heap = &mut *vm.heap;
|
|
218
|
+
// Check for slice first (Value::Ref pointing to HeapData::Slice)
|
|
219
|
+
if let Value::Ref(id) = key
|
|
220
|
+
&& let HeapData::Slice(slice) = heap.get(*id)
|
|
221
|
+
{
|
|
222
|
+
// Clone the slice to release the borrow on heap before calling getitem_slice
|
|
223
|
+
let slice = slice.clone();
|
|
224
|
+
return self.getitem_slice(&slice, heap);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Extract integer index, accepting Int, Bool (True=1, False=0), and LongInt
|
|
228
|
+
let index = key.as_index(heap, Type::List)?;
|
|
229
|
+
|
|
230
|
+
// Convert to usize, handling negative indices (Python-style: -1 = last element)
|
|
231
|
+
let len = i64::try_from(self.items.len()).expect("list length exceeds i64::MAX");
|
|
232
|
+
let normalized_index = if index < 0 { index + len } else { index };
|
|
233
|
+
|
|
234
|
+
// Bounds check
|
|
235
|
+
if normalized_index < 0 || normalized_index >= len {
|
|
236
|
+
return Err(ExcType::list_index_error());
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Return clone of the item with proper refcount increment
|
|
240
|
+
// Safety: normalized_index is validated to be in [0, len) above
|
|
241
|
+
let idx = usize::try_from(normalized_index).expect("list index validated non-negative");
|
|
242
|
+
Ok(self.items[idx].clone_with_heap(heap))
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
fn py_setitem(&mut self, key: Value, value: Value, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<()> {
|
|
246
|
+
let heap = &mut *vm.heap;
|
|
247
|
+
defer_drop!(key, heap);
|
|
248
|
+
defer_drop_mut!(value, heap);
|
|
249
|
+
|
|
250
|
+
// Extract integer index, accepting Int, Bool (True=1, False=0), and LongInt.
|
|
251
|
+
// Note: The LongInt-to-i64 conversion is defensive code. In normal execution,
|
|
252
|
+
// heap-allocated LongInt values always exceed i64 range because into_value()
|
|
253
|
+
// demotes i64-fitting values to Value::Int. However, this could be reached via
|
|
254
|
+
// deserialization of crafted snapshot data.
|
|
255
|
+
let index = match key {
|
|
256
|
+
Value::Int(i) => *i,
|
|
257
|
+
Value::Bool(b) => i64::from(*b),
|
|
258
|
+
Value::Ref(heap_id) => {
|
|
259
|
+
if let HeapData::LongInt(li) = heap.get(*heap_id) {
|
|
260
|
+
if let Some(i) = li.to_i64() {
|
|
261
|
+
i
|
|
262
|
+
} else {
|
|
263
|
+
return Err(ExcType::index_error_int_too_large());
|
|
264
|
+
}
|
|
265
|
+
} else {
|
|
266
|
+
let key_type = key.py_type(heap);
|
|
267
|
+
return Err(ExcType::type_error_list_assignment_indices(key_type));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
_ => {
|
|
271
|
+
let key_type = key.py_type(heap);
|
|
272
|
+
return Err(ExcType::type_error_list_assignment_indices(key_type));
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
// Normalize negative indices (Python-style: -1 = last element)
|
|
277
|
+
let len = i64::try_from(self.items.len()).expect("list length exceeds i64::MAX");
|
|
278
|
+
let normalized_index = if index < 0 { index + len } else { index };
|
|
279
|
+
|
|
280
|
+
// Bounds check
|
|
281
|
+
if normalized_index < 0 || normalized_index >= len {
|
|
282
|
+
return Err(ExcType::list_assignment_index_error());
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
let idx = usize::try_from(normalized_index).expect("index validated non-negative");
|
|
286
|
+
|
|
287
|
+
// Update contains_refs if storing a Ref (must check before swap,
|
|
288
|
+
// since after swap `value` holds the old item)
|
|
289
|
+
if matches!(*value, Value::Ref(_)) {
|
|
290
|
+
self.contains_refs = true;
|
|
291
|
+
heap.mark_potential_cycle();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Replace value (old one dropped by defer_drop_mut guard)
|
|
295
|
+
std::mem::swap(&mut self.items[idx], value);
|
|
296
|
+
|
|
297
|
+
Ok(())
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
fn py_eq(&self, other: &Self, vm: &mut VM<'_, '_, impl ResourceTracker>) -> Result<bool, ResourceError> {
|
|
301
|
+
if self.items.len() != other.items.len() {
|
|
302
|
+
return Ok(false);
|
|
303
|
+
}
|
|
304
|
+
let token = vm.heap.incr_recursion_depth()?;
|
|
305
|
+
defer_drop!(token, vm);
|
|
306
|
+
for (i1, i2) in self.items.iter().zip(&other.items) {
|
|
307
|
+
vm.heap.check_time()?;
|
|
308
|
+
if !i1.py_eq(i2, vm)? {
|
|
309
|
+
return Ok(false);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
Ok(true)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
fn py_dec_ref_ids(&mut self, stack: &mut Vec<HeapId>) {
|
|
316
|
+
// Skip iteration if no refs - major GC optimization for lists of primitives
|
|
317
|
+
if !self.contains_refs {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
for obj in &mut self.items {
|
|
321
|
+
if let Value::Ref(id) = obj {
|
|
322
|
+
stack.push(*id);
|
|
323
|
+
#[cfg(feature = "ref-count-panic")]
|
|
324
|
+
obj.dec_ref_forget();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
fn py_bool(&self, _vm: &VM<'_, '_, impl ResourceTracker>) -> bool {
|
|
330
|
+
!self.items.is_empty()
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
fn py_repr_fmt(
|
|
334
|
+
&self,
|
|
335
|
+
f: &mut impl Write,
|
|
336
|
+
vm: &VM<'_, '_, impl ResourceTracker>,
|
|
337
|
+
heap_ids: &mut AHashSet<HeapId>,
|
|
338
|
+
) -> std::fmt::Result {
|
|
339
|
+
repr_sequence_fmt('[', ']', &self.items, f, vm, heap_ids)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
fn py_add(
|
|
343
|
+
&self,
|
|
344
|
+
other: &Self,
|
|
345
|
+
vm: &mut VM<'_, '_, impl ResourceTracker>,
|
|
346
|
+
) -> Result<Option<Value>, crate::resource::ResourceError> {
|
|
347
|
+
let heap = &mut *vm.heap;
|
|
348
|
+
// Clone both lists' contents with proper refcounting
|
|
349
|
+
let mut result: Vec<Value> = self.items.iter().map(|obj| obj.clone_with_heap(heap)).collect();
|
|
350
|
+
let other_cloned: Vec<Value> = other.items.iter().map(|obj| obj.clone_with_heap(heap)).collect();
|
|
351
|
+
result.extend(other_cloned);
|
|
352
|
+
let id = heap.allocate(HeapData::List(Self::new(result)))?;
|
|
353
|
+
Ok(Some(Value::Ref(id)))
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
fn py_iadd(
|
|
357
|
+
&mut self,
|
|
358
|
+
other: &Value,
|
|
359
|
+
vm: &mut VM<'_, '_, impl ResourceTracker>,
|
|
360
|
+
self_id: Option<HeapId>,
|
|
361
|
+
) -> Result<bool, crate::resource::ResourceError> {
|
|
362
|
+
let heap = &mut *vm.heap;
|
|
363
|
+
// Extract the value ID first, keeping `other` around to drop later
|
|
364
|
+
let Value::Ref(other_id) = other else { return Ok(false) };
|
|
365
|
+
|
|
366
|
+
if Some(*other_id) == self_id {
|
|
367
|
+
// Self-extend: clone our own items with proper refcounting
|
|
368
|
+
let items = self
|
|
369
|
+
.items
|
|
370
|
+
.iter()
|
|
371
|
+
.map(|obj| obj.clone_with_heap(heap))
|
|
372
|
+
.collect::<Vec<_>>();
|
|
373
|
+
// If we're self-extending and have refs, mark potential cycle
|
|
374
|
+
if self.contains_refs {
|
|
375
|
+
heap.mark_potential_cycle();
|
|
376
|
+
}
|
|
377
|
+
self.items.extend(items);
|
|
378
|
+
} else {
|
|
379
|
+
// Get items from other list using iadd_extend_from_heap helper
|
|
380
|
+
// This handles the borrow checker limitations with lifetime propagation
|
|
381
|
+
let prev_len = self.items.len();
|
|
382
|
+
if !heap.iadd_extend_list(*other_id, &mut self.items) {
|
|
383
|
+
return Ok(false);
|
|
384
|
+
}
|
|
385
|
+
// Check if we added any refs and mark potential cycle
|
|
386
|
+
if self.contains_refs {
|
|
387
|
+
// Already had refs, but adding more may create cycles
|
|
388
|
+
heap.mark_potential_cycle();
|
|
389
|
+
} else {
|
|
390
|
+
for item in &self.items[prev_len..] {
|
|
391
|
+
if matches!(item, Value::Ref(_)) {
|
|
392
|
+
self.contains_refs = true;
|
|
393
|
+
heap.mark_potential_cycle();
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
Ok(true)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/// Intercepts `sort` to call `do_list_sort` (which needs `PrintWriter` for key functions),
|
|
404
|
+
/// and delegates all other methods to `call_list_method`.
|
|
405
|
+
fn py_call_attr(
|
|
406
|
+
&mut self,
|
|
407
|
+
_self_id: HeapId,
|
|
408
|
+
vm: &mut VM<'_, '_, impl ResourceTracker>,
|
|
409
|
+
attr: &EitherStr,
|
|
410
|
+
args: ArgValues,
|
|
411
|
+
) -> RunResult<CallResult> {
|
|
412
|
+
if attr.static_string() == Some(StaticStrings::Sort) {
|
|
413
|
+
do_list_sort(self, args, vm)?;
|
|
414
|
+
return Ok(CallResult::Value(Value::None));
|
|
415
|
+
}
|
|
416
|
+
let args_guard = HeapGuard::new(args, vm.heap);
|
|
417
|
+
let Some(method) = attr.static_string() else {
|
|
418
|
+
return Err(ExcType::attribute_error(Type::List, attr.as_str(vm.interns)));
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
let args = args_guard.into_inner();
|
|
422
|
+
call_list_method(self, method, args, vm).map(CallResult::Value)
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/// Dispatches a method call on a list value.
|
|
427
|
+
///
|
|
428
|
+
/// This is the unified entry point for list method calls.
|
|
429
|
+
///
|
|
430
|
+
/// # Arguments
|
|
431
|
+
/// * `list` - The list to call the method on
|
|
432
|
+
/// * `method` - The method to call (e.g., `StaticStrings::Append`)
|
|
433
|
+
/// * `args` - The method arguments
|
|
434
|
+
/// * `heap` - The heap for allocation and reference counting
|
|
435
|
+
fn call_list_method(
|
|
436
|
+
list: &mut List,
|
|
437
|
+
method: StaticStrings,
|
|
438
|
+
args: ArgValues,
|
|
439
|
+
vm: &mut VM<'_, '_, impl ResourceTracker>,
|
|
440
|
+
) -> RunResult<Value> {
|
|
441
|
+
let heap = &mut *vm.heap;
|
|
442
|
+
match method {
|
|
443
|
+
StaticStrings::Append => {
|
|
444
|
+
let item = args.get_one_arg("list.append", heap)?;
|
|
445
|
+
list.append(heap, item);
|
|
446
|
+
Ok(Value::None)
|
|
447
|
+
}
|
|
448
|
+
StaticStrings::Insert => list_insert(list, args, heap),
|
|
449
|
+
StaticStrings::Pop => list_pop(list, args, heap),
|
|
450
|
+
StaticStrings::Remove => list_remove(list, args, vm),
|
|
451
|
+
StaticStrings::Clear => {
|
|
452
|
+
args.check_zero_args("list.clear", heap)?;
|
|
453
|
+
list_clear(list, heap);
|
|
454
|
+
Ok(Value::None)
|
|
455
|
+
}
|
|
456
|
+
StaticStrings::Copy => {
|
|
457
|
+
args.check_zero_args("list.copy", heap)?;
|
|
458
|
+
Ok(list_copy(list, heap)?)
|
|
459
|
+
}
|
|
460
|
+
StaticStrings::Extend => list_extend(list, args, vm),
|
|
461
|
+
StaticStrings::Index => list_index(list, args, vm),
|
|
462
|
+
StaticStrings::Count => list_count(list, args, vm),
|
|
463
|
+
StaticStrings::Reverse => {
|
|
464
|
+
args.check_zero_args("list.reverse", heap)?;
|
|
465
|
+
list.items.reverse();
|
|
466
|
+
Ok(Value::None)
|
|
467
|
+
}
|
|
468
|
+
// Note: list.sort is handled by py_call_attr which intercepts it before reaching here
|
|
469
|
+
_ => {
|
|
470
|
+
args.drop_with_heap(heap);
|
|
471
|
+
Err(ExcType::attribute_error(Type::List, method.into()))
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/// Implements Python's `list.insert(index, item)` method.
|
|
477
|
+
fn list_insert(list: &mut List, args: ArgValues, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
|
|
478
|
+
let (index_obj, item) = args.get_two_args("insert", heap)?;
|
|
479
|
+
defer_drop!(index_obj, heap);
|
|
480
|
+
let mut item_guard = HeapGuard::new(item, heap);
|
|
481
|
+
let heap = item_guard.heap();
|
|
482
|
+
// Python's insert() handles negative indices by adding len
|
|
483
|
+
// If still negative after adding len, clamps to 0
|
|
484
|
+
// If >= len, appends to end
|
|
485
|
+
let index_i64 = index_obj.as_int(heap)?;
|
|
486
|
+
let len = list.items.len();
|
|
487
|
+
let len_i64 = i64::try_from(len).expect("list length exceeds i64::MAX");
|
|
488
|
+
let index = if index_i64 < 0 {
|
|
489
|
+
// Negative index: add length, clamp to 0 if still negative
|
|
490
|
+
let adjusted = index_i64 + len_i64;
|
|
491
|
+
usize::try_from(adjusted).unwrap_or(0)
|
|
492
|
+
} else {
|
|
493
|
+
// Positive index: clamp to len if too large
|
|
494
|
+
usize::try_from(index_i64).unwrap_or(len)
|
|
495
|
+
};
|
|
496
|
+
let (item, heap) = item_guard.into_parts();
|
|
497
|
+
list.insert(heap, index, item);
|
|
498
|
+
Ok(Value::None)
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/// Implements Python's `list.pop([index])` method.
|
|
502
|
+
///
|
|
503
|
+
/// Removes the item at the given index (default: -1) and returns it.
|
|
504
|
+
/// Raises IndexError if the list is empty or the index is out of range.
|
|
505
|
+
fn list_pop(list: &mut List, args: ArgValues, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
|
|
506
|
+
let index_arg = args.get_zero_one_arg("list.pop", heap)?;
|
|
507
|
+
|
|
508
|
+
// Validate index type FIRST (if provided), matching Python's validation order.
|
|
509
|
+
// Python raises TypeError for bad index type even on empty list.
|
|
510
|
+
let index_i64 = if let Some(v) = index_arg {
|
|
511
|
+
let result = v.as_int(heap);
|
|
512
|
+
v.drop_with_heap(heap);
|
|
513
|
+
result?
|
|
514
|
+
} else {
|
|
515
|
+
-1
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
// THEN check empty list
|
|
519
|
+
if list.items.is_empty() {
|
|
520
|
+
return Err(ExcType::index_error_pop_empty_list());
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Normalize index
|
|
524
|
+
let len = list.items.len();
|
|
525
|
+
let len_i64 = i64::try_from(len).expect("list length exceeds i64::MAX");
|
|
526
|
+
let normalized = if index_i64 < 0 { index_i64 + len_i64 } else { index_i64 };
|
|
527
|
+
|
|
528
|
+
// Bounds check
|
|
529
|
+
if normalized < 0 || normalized >= len_i64 {
|
|
530
|
+
return Err(ExcType::index_error_pop_out_of_range());
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Remove and return the item
|
|
534
|
+
let idx = usize::try_from(normalized).expect("index validated non-negative");
|
|
535
|
+
Ok(list.items.remove(idx))
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/// Implements Python's `list.remove(value)` method.
|
|
539
|
+
///
|
|
540
|
+
/// Removes the first occurrence of value. Raises ValueError if not found.
|
|
541
|
+
fn list_remove(list: &mut List, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
|
|
542
|
+
let value = args.get_one_arg("list.remove", vm.heap)?;
|
|
543
|
+
defer_drop!(value, vm);
|
|
544
|
+
|
|
545
|
+
// Find the first matching element
|
|
546
|
+
let mut found_idx = None;
|
|
547
|
+
for (i, item) in list.items.iter().enumerate() {
|
|
548
|
+
vm.heap.check_time()?;
|
|
549
|
+
if value.py_eq(item, vm)? {
|
|
550
|
+
found_idx = Some(i);
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
match found_idx {
|
|
556
|
+
Some(idx) => {
|
|
557
|
+
// Remove the element and drop its refcount
|
|
558
|
+
let removed = list.items.remove(idx);
|
|
559
|
+
removed.drop_with_heap(vm.heap);
|
|
560
|
+
Ok(Value::None)
|
|
561
|
+
}
|
|
562
|
+
None => Err(ExcType::value_error_remove_not_in_list()),
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/// Implements Python's `list.clear()` method.
|
|
567
|
+
///
|
|
568
|
+
/// Removes all items from the list.
|
|
569
|
+
fn list_clear(list: &mut List, heap: &mut Heap<impl ResourceTracker>) {
|
|
570
|
+
list.items.drain(..).drop_with_heap(heap);
|
|
571
|
+
// Note: contains_refs stays true even if all refs removed, per conservative GC strategy
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/// Implements Python's `list.copy()` method.
|
|
575
|
+
///
|
|
576
|
+
/// Returns a shallow copy of the list.
|
|
577
|
+
fn list_copy(list: &List, heap: &mut Heap<impl ResourceTracker>) -> Result<Value, ResourceError> {
|
|
578
|
+
let items: Vec<Value> = list.items.iter().map(|v| v.clone_with_heap(heap)).collect();
|
|
579
|
+
let heap_id = heap.allocate(HeapData::List(List::new(items)))?;
|
|
580
|
+
Ok(Value::Ref(heap_id))
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/// Implements Python's `list.extend(iterable)` method.
|
|
584
|
+
///
|
|
585
|
+
/// Extends the list by appending all items from the iterable.
|
|
586
|
+
fn list_extend(list: &mut List, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
|
|
587
|
+
let iterable = args.get_one_arg("list.extend", vm.heap)?;
|
|
588
|
+
let items: SmallVec<[_; 2]> = MontyIter::new(iterable, vm)?.collect(vm)?;
|
|
589
|
+
|
|
590
|
+
// Add each item to the list
|
|
591
|
+
for item in items {
|
|
592
|
+
list.append(vm.heap, item);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
Ok(Value::None)
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/// Implements Python's `list.index(value[, start[, end]])` method.
|
|
599
|
+
///
|
|
600
|
+
/// Returns the index of the first occurrence of value.
|
|
601
|
+
/// Raises ValueError if the value is not found.
|
|
602
|
+
fn list_index(list: &List, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
|
|
603
|
+
let pos_args = args.into_pos_only("list.index", vm.heap)?;
|
|
604
|
+
defer_drop!(pos_args, vm);
|
|
605
|
+
|
|
606
|
+
let len = list.items.len();
|
|
607
|
+
let (value, start, end) = match pos_args.as_slice() {
|
|
608
|
+
[] => return Err(ExcType::type_error_at_least("list.index", 1, 0)),
|
|
609
|
+
[value] => (value, 0, len),
|
|
610
|
+
[value, start_arg] => {
|
|
611
|
+
let start = normalize_list_index(start_arg.as_int(vm.heap)?, len);
|
|
612
|
+
(value, start, len)
|
|
613
|
+
}
|
|
614
|
+
[value, start_arg, end_arg] => {
|
|
615
|
+
let start = normalize_list_index(start_arg.as_int(vm.heap)?, len);
|
|
616
|
+
let end = normalize_list_index(end_arg.as_int(vm.heap)?, len).max(start);
|
|
617
|
+
(value, start, end)
|
|
618
|
+
}
|
|
619
|
+
other => return Err(ExcType::type_error_at_most("list.index", 3, other.len())),
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
// Search for the value in the specified range
|
|
623
|
+
for (i, item) in list.items[start..end].iter().enumerate() {
|
|
624
|
+
vm.heap.check_time()?;
|
|
625
|
+
if value.py_eq(item, vm)? {
|
|
626
|
+
let idx = i64::try_from(start + i).expect("index exceeds i64::MAX");
|
|
627
|
+
return Ok(Value::Int(idx));
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
Err(ExcType::value_error_not_in_list())
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/// Implements Python's `list.count(value)` method.
|
|
635
|
+
///
|
|
636
|
+
/// Returns the number of occurrences of value in the list.
|
|
637
|
+
fn list_count(list: &List, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> RunResult<Value> {
|
|
638
|
+
let value = args.get_one_arg("list.count", vm.heap)?;
|
|
639
|
+
defer_drop!(value, vm);
|
|
640
|
+
|
|
641
|
+
let mut count: usize = 0;
|
|
642
|
+
for item in &list.items {
|
|
643
|
+
vm.heap.check_time()?;
|
|
644
|
+
if value.py_eq(item, vm)? {
|
|
645
|
+
count += 1;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
let count_i64 = i64::try_from(count).expect("count exceeds i64::MAX");
|
|
650
|
+
Ok(Value::Int(count_i64))
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/// Normalizes a Python-style list index to a valid index in range [0, len].
|
|
654
|
+
fn normalize_list_index(index: i64, len: usize) -> usize {
|
|
655
|
+
if index < 0 {
|
|
656
|
+
let abs_index = usize::try_from(-index).unwrap_or(usize::MAX);
|
|
657
|
+
len.saturating_sub(abs_index)
|
|
658
|
+
} else {
|
|
659
|
+
usize::try_from(index).unwrap_or(len).min(len)
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/// Performs an in-place sort on a list with optional key function and reverse flag.
|
|
664
|
+
fn do_list_sort(list: &mut List, args: ArgValues, vm: &mut VM<'_, '_, impl ResourceTracker>) -> Result<(), RunError> {
|
|
665
|
+
// Parse keyword-only arguments: key and reverse
|
|
666
|
+
let (key_arg, reverse_arg) = args.extract_two_kwargs_only("list.sort", "key", "reverse", vm.heap, vm.interns)?;
|
|
667
|
+
|
|
668
|
+
// Convert reverse to bool (default false)
|
|
669
|
+
let reverse = if let Some(v) = reverse_arg {
|
|
670
|
+
let result = v.py_bool(vm);
|
|
671
|
+
v.drop_with_heap(vm);
|
|
672
|
+
result
|
|
673
|
+
} else {
|
|
674
|
+
false
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
// Handle key function (None means no key function)
|
|
678
|
+
let key_fn = match key_arg {
|
|
679
|
+
Some(v) if matches!(v, Value::None) => {
|
|
680
|
+
v.drop_with_heap(vm);
|
|
681
|
+
None
|
|
682
|
+
}
|
|
683
|
+
other => other,
|
|
684
|
+
};
|
|
685
|
+
defer_drop!(key_fn, vm);
|
|
686
|
+
|
|
687
|
+
// Step 1: Borrow from the list for in-place sorting
|
|
688
|
+
let items = list.as_vec_mut();
|
|
689
|
+
|
|
690
|
+
// 2. Compute key values if a key function was provided, otherwise we'll sort by the items themselves
|
|
691
|
+
let mut keys_guard;
|
|
692
|
+
let (compare_values, vm) = if let Some(f) = key_fn {
|
|
693
|
+
let keys: Vec<Value> = Vec::with_capacity(items.len());
|
|
694
|
+
// Use a HeapGuard to ensure that if key function evaluation fails partway through,
|
|
695
|
+
// we clean up any keys that were successfully computed
|
|
696
|
+
keys_guard = HeapGuard::new(keys, vm);
|
|
697
|
+
let (keys, vm) = keys_guard.as_parts_mut();
|
|
698
|
+
items
|
|
699
|
+
.iter()
|
|
700
|
+
.map(|item| {
|
|
701
|
+
let item = item.clone_with_heap(vm);
|
|
702
|
+
vm.evaluate_function("sorted() key argument", f, ArgValues::One(item))
|
|
703
|
+
})
|
|
704
|
+
.process_results(|keys_iter| keys.extend(keys_iter))?;
|
|
705
|
+
keys_guard.as_parts()
|
|
706
|
+
} else {
|
|
707
|
+
(&*items, vm)
|
|
708
|
+
};
|
|
709
|
+
|
|
710
|
+
// 3. Sort indices by comparing key values (or items themselves if no key)
|
|
711
|
+
let len = compare_values.len();
|
|
712
|
+
let mut indices: Vec<usize> = (0..len).collect();
|
|
713
|
+
|
|
714
|
+
sort_indices(&mut indices, compare_values, reverse, vm)?;
|
|
715
|
+
|
|
716
|
+
// 4. Rearrange items in-place according to the sorted permutation
|
|
717
|
+
apply_permutation(items, &mut indices);
|
|
718
|
+
Ok(())
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/// Writes a formatted sequence of values to a formatter.
|
|
722
|
+
///
|
|
723
|
+
/// This helper function is used to implement `__repr__` for sequence types like
|
|
724
|
+
/// lists and tuples. It writes items as comma-separated repr interns.
|
|
725
|
+
///
|
|
726
|
+
/// # Arguments
|
|
727
|
+
/// * `start` - The opening character (e.g., '[' for lists, '(' for tuples)
|
|
728
|
+
/// * `end` - The closing character (e.g., ']' for lists, ')' for tuples)
|
|
729
|
+
/// * `items` - The slice of values to format
|
|
730
|
+
/// * `f` - The formatter to write to
|
|
731
|
+
/// * `vm` - The VM for resolving value references and looking up interned strings
|
|
732
|
+
/// * `heap_ids` - Set of heap IDs being repr'd (for cycle detection)
|
|
733
|
+
pub(crate) fn repr_sequence_fmt(
|
|
734
|
+
start: char,
|
|
735
|
+
end: char,
|
|
736
|
+
items: &[Value],
|
|
737
|
+
f: &mut impl Write,
|
|
738
|
+
vm: &VM<'_, '_, impl ResourceTracker>,
|
|
739
|
+
heap_ids: &mut AHashSet<HeapId>,
|
|
740
|
+
) -> std::fmt::Result {
|
|
741
|
+
// Check depth limit before recursing
|
|
742
|
+
let heap = &*vm.heap;
|
|
743
|
+
let Some(token) = heap.incr_recursion_depth_for_repr() else {
|
|
744
|
+
return f.write_str("...");
|
|
745
|
+
};
|
|
746
|
+
crate::defer_drop_immutable_heap!(token, heap);
|
|
747
|
+
|
|
748
|
+
f.write_char(start)?;
|
|
749
|
+
let mut iter = items.iter();
|
|
750
|
+
if let Some(first) = iter.next() {
|
|
751
|
+
first.py_repr_fmt(f, vm, heap_ids)?;
|
|
752
|
+
for item in iter {
|
|
753
|
+
if heap.check_time().is_err() {
|
|
754
|
+
f.write_str(", ...[timeout]")?;
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
f.write_str(", ")?;
|
|
758
|
+
item.py_repr_fmt(f, vm, heap_ids)?;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
f.write_char(end)?;
|
|
762
|
+
|
|
763
|
+
Ok(())
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/// Helper to extract items from a slice for list/tuple slicing.
|
|
767
|
+
///
|
|
768
|
+
/// Handles both positive and negative step values. For negative step,
|
|
769
|
+
/// iterates backward from start down to (but not including) stop.
|
|
770
|
+
///
|
|
771
|
+
/// Returns a new Vec of cloned values with proper refcount increments.
|
|
772
|
+
/// Checks the time limit on each iteration to enforce timeouts during slicing.
|
|
773
|
+
///
|
|
774
|
+
/// Note: step must be non-zero (callers should validate this via `slice.indices()`).
|
|
775
|
+
pub(crate) fn get_slice_items(
|
|
776
|
+
items: &[Value],
|
|
777
|
+
start: usize,
|
|
778
|
+
stop: usize,
|
|
779
|
+
step: i64,
|
|
780
|
+
heap: &mut Heap<impl ResourceTracker>,
|
|
781
|
+
) -> RunResult<Vec<Value>> {
|
|
782
|
+
let mut result = Vec::new();
|
|
783
|
+
|
|
784
|
+
// try_from succeeds for non-negative step; step==0 rejected upstream by slice.indices()
|
|
785
|
+
if let Ok(step_usize) = usize::try_from(step) {
|
|
786
|
+
// Positive step: iterate forward
|
|
787
|
+
let mut i = start;
|
|
788
|
+
while i < stop && i < items.len() {
|
|
789
|
+
heap.check_time()?;
|
|
790
|
+
result.push(items[i].clone_with_heap(heap));
|
|
791
|
+
i += step_usize;
|
|
792
|
+
}
|
|
793
|
+
} else {
|
|
794
|
+
// Negative step: iterate backward
|
|
795
|
+
// start is the highest index, stop is the sentinel
|
|
796
|
+
// stop > items.len() means "go to the beginning"
|
|
797
|
+
let step_abs = usize::try_from(-step).expect("step is negative so -step is positive");
|
|
798
|
+
let step_abs_i64 = i64::try_from(step_abs).expect("step magnitude fits in i64");
|
|
799
|
+
let mut i = i64::try_from(start).expect("start index fits in i64");
|
|
800
|
+
let stop_i64 = if stop > items.len() {
|
|
801
|
+
-1
|
|
802
|
+
} else {
|
|
803
|
+
i64::try_from(stop).expect("stop bounded by items.len() fits in i64")
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
while let Ok(i_usize) = usize::try_from(i) {
|
|
807
|
+
if i_usize >= items.len() || i <= stop_i64 {
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
heap.check_time()?;
|
|
811
|
+
result.push(items[i_usize].clone_with_heap(heap));
|
|
812
|
+
i -= step_abs_i64;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
Ok(result)
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
#[cfg(test)]
|
|
820
|
+
mod tests {
|
|
821
|
+
use num_bigint::BigInt;
|
|
822
|
+
|
|
823
|
+
use super::*;
|
|
824
|
+
use crate::{
|
|
825
|
+
PrintWriter,
|
|
826
|
+
intern::{InternerBuilder, Interns},
|
|
827
|
+
resource::NoLimitTracker,
|
|
828
|
+
types::LongInt,
|
|
829
|
+
};
|
|
830
|
+
|
|
831
|
+
/// Creates a minimal Interns for testing.
|
|
832
|
+
fn create_test_interns() -> Interns {
|
|
833
|
+
let interner = InternerBuilder::new("");
|
|
834
|
+
Interns::new(interner, vec![])
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/// Creates a heap with a list and a LongInt index, bypassing into_value() demotion.
|
|
838
|
+
///
|
|
839
|
+
/// This allows testing the defensive code path where a LongInt contains an i64-fitting value.
|
|
840
|
+
fn create_heap_with_list_and_longint(
|
|
841
|
+
list_items: Vec<Value>,
|
|
842
|
+
index_value: BigInt,
|
|
843
|
+
) -> (Heap<NoLimitTracker>, HeapId, HeapId) {
|
|
844
|
+
let mut heap = Heap::new(16, NoLimitTracker);
|
|
845
|
+
let list = List::new(list_items);
|
|
846
|
+
let list_id = heap.allocate(HeapData::List(list)).unwrap();
|
|
847
|
+
let long_int = LongInt::new(index_value);
|
|
848
|
+
let index_id = heap.allocate(HeapData::LongInt(long_int)).unwrap();
|
|
849
|
+
(heap, list_id, index_id)
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/// Tests py_setitem with a LongInt index that fits in i64.
|
|
853
|
+
///
|
|
854
|
+
/// This is a defensive code path - normally unreachable because LongInt::into_value()
|
|
855
|
+
/// demotes i64-fitting values to Value::Int. However, it could be reached via
|
|
856
|
+
/// deserialization of crafted snapshot data.
|
|
857
|
+
#[test]
|
|
858
|
+
fn py_setitem_longint_fits_in_i64() {
|
|
859
|
+
let (mut heap, list_id, index_id) =
|
|
860
|
+
create_heap_with_list_and_longint(vec![Value::Int(10), Value::Int(20), Value::Int(30)], BigInt::from(1));
|
|
861
|
+
let interns = create_test_interns();
|
|
862
|
+
|
|
863
|
+
// Use heap.with_entry_mut to avoid double mutable borrow
|
|
864
|
+
let key = Value::Ref(index_id);
|
|
865
|
+
let new_value = Value::Int(99);
|
|
866
|
+
heap.inc_ref(index_id);
|
|
867
|
+
|
|
868
|
+
let mut vm = VM::new(Vec::new(), &mut heap, &interns, PrintWriter::Disabled);
|
|
869
|
+
let result = Heap::with_entry_mut(&mut vm, list_id, |vm, mut data| data.py_setitem(key, new_value, vm));
|
|
870
|
+
|
|
871
|
+
assert!(result.is_ok());
|
|
872
|
+
|
|
873
|
+
// Verify the list was updated by checking it matches expected Int value
|
|
874
|
+
let HeapData::List(list) = heap.get(list_id) else {
|
|
875
|
+
panic!("expected list");
|
|
876
|
+
};
|
|
877
|
+
assert!(matches!(list.as_slice()[1], Value::Int(99)));
|
|
878
|
+
|
|
879
|
+
// Clean up
|
|
880
|
+
Value::Ref(list_id).drop_with_heap(&mut heap);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/// Tests py_setitem with a negative LongInt index that fits in i64.
|
|
884
|
+
#[test]
|
|
885
|
+
fn py_setitem_longint_negative_fits_in_i64() {
|
|
886
|
+
let (mut heap, list_id, index_id) = create_heap_with_list_and_longint(
|
|
887
|
+
vec![Value::Int(10), Value::Int(20), Value::Int(30)],
|
|
888
|
+
BigInt::from(-1), // Last element
|
|
889
|
+
);
|
|
890
|
+
let interns = create_test_interns();
|
|
891
|
+
|
|
892
|
+
let key = Value::Ref(index_id);
|
|
893
|
+
let new_value = Value::Int(99);
|
|
894
|
+
heap.inc_ref(index_id);
|
|
895
|
+
|
|
896
|
+
let mut vm = VM::new(Vec::new(), &mut heap, &interns, PrintWriter::Disabled);
|
|
897
|
+
let result = Heap::with_entry_mut(&mut vm, list_id, |vm, mut data| data.py_setitem(key, new_value, vm));
|
|
898
|
+
|
|
899
|
+
assert!(result.is_ok());
|
|
900
|
+
|
|
901
|
+
// Verify the last element was updated
|
|
902
|
+
let HeapData::List(list) = heap.get(list_id) else {
|
|
903
|
+
panic!("expected list");
|
|
904
|
+
};
|
|
905
|
+
assert!(matches!(list.as_slice()[2], Value::Int(99)));
|
|
906
|
+
|
|
907
|
+
Value::Ref(list_id).drop_with_heap(&mut heap);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/// Tests py_setitem with i64::MAX as a LongInt index.
|
|
911
|
+
#[test]
|
|
912
|
+
fn py_setitem_longint_at_i64_max() {
|
|
913
|
+
let (mut heap, list_id, index_id) =
|
|
914
|
+
create_heap_with_list_and_longint(vec![Value::Int(10)], BigInt::from(i64::MAX));
|
|
915
|
+
let interns = create_test_interns();
|
|
916
|
+
|
|
917
|
+
let key = Value::Ref(index_id);
|
|
918
|
+
let new_value = Value::Int(99);
|
|
919
|
+
heap.inc_ref(index_id);
|
|
920
|
+
|
|
921
|
+
// This should fail with IndexError because i64::MAX is out of bounds for a 1-element list
|
|
922
|
+
let mut vm = VM::new(Vec::new(), &mut heap, &interns, PrintWriter::Disabled);
|
|
923
|
+
let result = Heap::with_entry_mut(&mut vm, list_id, |vm, mut data| data.py_setitem(key, new_value, vm));
|
|
924
|
+
|
|
925
|
+
assert!(result.is_err());
|
|
926
|
+
|
|
927
|
+
Value::Ref(list_id).drop_with_heap(&mut heap);
|
|
928
|
+
}
|
|
929
|
+
}
|