Showing preview only (4,317K chars total). Download the full file or copy to clipboard to get everything.
Repository: pydantic/monty
Branch: main
Commit: 60538204fd9c
Files: 724
Total size: 4.0 MB
Directory structure:
gitextract_527ed2df/
├── .cargo/
│ └── config.toml
├── .claude/
│ ├── settings.json
│ └── skills/
│ ├── coverage/
│ │ └── SKILL.md
│ ├── fastmod/
│ │ └── SKILL.md
│ └── python-playground/
│ └── SKILL.md
├── .codecov.yml
├── .github/
│ ├── actions/
│ │ └── build-pgo-wheel/
│ │ └── action.yml
│ └── workflows/
│ ├── ci.yml
│ ├── codspeed.yml
│ └── init-npm-packages.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .python-version
├── .rustfmt.toml
├── CLAUDE.md
├── Cargo.toml
├── LICENSE
├── Makefile
├── README.md
├── RELEASING.md
├── crates/
│ ├── fuzz/
│ │ ├── Cargo.toml
│ │ └── fuzz_targets/
│ │ ├── string_input_panic.rs
│ │ └── tokens_input_panic.rs
│ ├── monty/
│ │ ├── Cargo.toml
│ │ ├── benches/
│ │ │ └── main.rs
│ │ ├── build.rs
│ │ ├── src/
│ │ │ ├── args.rs
│ │ │ ├── asyncio.rs
│ │ │ ├── builtins/
│ │ │ │ ├── abs.rs
│ │ │ │ ├── all.rs
│ │ │ │ ├── any.rs
│ │ │ │ ├── bin.rs
│ │ │ │ ├── chr.rs
│ │ │ │ ├── divmod.rs
│ │ │ │ ├── enumerate.rs
│ │ │ │ ├── filter.rs
│ │ │ │ ├── getattr.rs
│ │ │ │ ├── hash.rs
│ │ │ │ ├── hex.rs
│ │ │ │ ├── id.rs
│ │ │ │ ├── isinstance.rs
│ │ │ │ ├── len.rs
│ │ │ │ ├── map.rs
│ │ │ │ ├── min_max.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── next.rs
│ │ │ │ ├── oct.rs
│ │ │ │ ├── ord.rs
│ │ │ │ ├── pow.rs
│ │ │ │ ├── print.rs
│ │ │ │ ├── repr.rs
│ │ │ │ ├── reversed.rs
│ │ │ │ ├── round.rs
│ │ │ │ ├── sorted.rs
│ │ │ │ ├── sum.rs
│ │ │ │ ├── type_.rs
│ │ │ │ └── zip.rs
│ │ │ ├── bytecode/
│ │ │ │ ├── builder.rs
│ │ │ │ ├── code.rs
│ │ │ │ ├── compiler.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── op.rs
│ │ │ │ └── vm/
│ │ │ │ ├── async_exec.rs
│ │ │ │ ├── attr.rs
│ │ │ │ ├── binary.rs
│ │ │ │ ├── call.rs
│ │ │ │ ├── collections.rs
│ │ │ │ ├── compare.rs
│ │ │ │ ├── exceptions.rs
│ │ │ │ ├── format.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── scheduler.rs
│ │ │ ├── exception_private.rs
│ │ │ ├── exception_public.rs
│ │ │ ├── expressions.rs
│ │ │ ├── fstring.rs
│ │ │ ├── function.rs
│ │ │ ├── heap.rs
│ │ │ ├── heap_data.rs
│ │ │ ├── heap_traits.rs
│ │ │ ├── intern.rs
│ │ │ ├── io.rs
│ │ │ ├── lib.rs
│ │ │ ├── modules/
│ │ │ │ ├── asyncio.rs
│ │ │ │ ├── math.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── os.rs
│ │ │ │ ├── pathlib.rs
│ │ │ │ ├── re.rs
│ │ │ │ ├── sys.rs
│ │ │ │ └── typing.rs
│ │ │ ├── namespace.rs
│ │ │ ├── object.rs
│ │ │ ├── os.rs
│ │ │ ├── parse.rs
│ │ │ ├── prepare.rs
│ │ │ ├── repl.rs
│ │ │ ├── resource.rs
│ │ │ ├── run.rs
│ │ │ ├── run_progress.rs
│ │ │ ├── signature.rs
│ │ │ ├── sorting.rs
│ │ │ ├── types/
│ │ │ │ ├── bytes.rs
│ │ │ │ ├── dataclass.rs
│ │ │ │ ├── dict.rs
│ │ │ │ ├── dict_view.rs
│ │ │ │ ├── iter.rs
│ │ │ │ ├── list.rs
│ │ │ │ ├── long_int.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── module.rs
│ │ │ │ ├── namedtuple.rs
│ │ │ │ ├── path.rs
│ │ │ │ ├── property.rs
│ │ │ │ ├── py_trait.rs
│ │ │ │ ├── range.rs
│ │ │ │ ├── re_match.rs
│ │ │ │ ├── re_pattern.rs
│ │ │ │ ├── set.rs
│ │ │ │ ├── slice.rs
│ │ │ │ ├── str.rs
│ │ │ │ ├── tuple.rs
│ │ │ │ └── type.rs
│ │ │ └── value.rs
│ │ ├── test_cases/
│ │ │ ├── args__dict_get_no_args.py
│ │ │ ├── args__dict_get_too_many.py
│ │ │ ├── args__dict_items_with_args.py
│ │ │ ├── args__dict_keys_with_args.py
│ │ │ ├── args__dict_pop_no_args.py
│ │ │ ├── args__dict_pop_too_many.py
│ │ │ ├── args__dict_values_with_args.py
│ │ │ ├── args__id_too_many.py
│ │ │ ├── args__len_no_args.py
│ │ │ ├── args__len_too_many.py
│ │ │ ├── args__len_type_error_int.py
│ │ │ ├── args__len_type_error_none.py
│ │ │ ├── args__list_append_no_args.py
│ │ │ ├── args__list_append_too_many.py
│ │ │ ├── args__list_insert_too_few.py
│ │ │ ├── args__list_insert_too_many.py
│ │ │ ├── args__repr_no_args.py
│ │ │ ├── arith__div_zero_float.py
│ │ │ ├── arith__div_zero_int.py
│ │ │ ├── arith__floordiv_zero_float.py
│ │ │ ├── arith__floordiv_zero_int.py
│ │ │ ├── arith__pow_zero_neg.py
│ │ │ ├── arith__pow_zero_neg_builtin.py
│ │ │ ├── assert__expr_fail.py
│ │ │ ├── assert__fail.py
│ │ │ ├── assert__fail_msg.py
│ │ │ ├── assert__fn_fail.py
│ │ │ ├── assert__ops.py
│ │ │ ├── async__asyncio_run.py
│ │ │ ├── async__basic.py
│ │ │ ├── async__closure.py
│ │ │ ├── async__double_await_coroutine.py
│ │ │ ├── async__exception.py
│ │ │ ├── async__ext_call.py
│ │ │ ├── async__gather_all.py
│ │ │ ├── async__nested_await.py
│ │ │ ├── async__nested_gather_ext.py
│ │ │ ├── async__not_awaitable.py
│ │ │ ├── async__not_imported.py
│ │ │ ├── async__recursion_depth_isolation.py
│ │ │ ├── async__return_types.py
│ │ │ ├── async__sequential.py
│ │ │ ├── async__traceback.py
│ │ │ ├── async__with_args.py
│ │ │ ├── attr__get_int_error.py
│ │ │ ├── attr__get_list_error.py
│ │ │ ├── attr__set_frozen_nonfield.py
│ │ │ ├── attr__set_int_error.py
│ │ │ ├── attr__set_list_error.py
│ │ │ ├── bench__kitchen_sink.py
│ │ │ ├── bool__ops.py
│ │ │ ├── builtin__add_type_error.py
│ │ │ ├── builtin__filter.py
│ │ │ ├── builtin__filter_not_iterable.py
│ │ │ ├── builtin__getattr.py
│ │ │ ├── builtin__iter_err_unpack_int.py
│ │ │ ├── builtin__iter_funcs.py
│ │ │ ├── builtin__iter_next.py
│ │ │ ├── builtin__map.py
│ │ │ ├── builtin__map_not_iterable.py
│ │ │ ├── builtin__math_funcs.py
│ │ │ ├── builtin__more_iter_funcs.py
│ │ │ ├── builtin__next_stop_iteration.py
│ │ │ ├── builtin__print_invalid_kwarg.py
│ │ │ ├── builtin__print_kwargs.py
│ │ │ ├── builtin__repr.py
│ │ │ ├── builtin__string_funcs.py
│ │ │ ├── bytes__decode_invalid_utf8.py
│ │ │ ├── bytes__endswith_str_error.py
│ │ │ ├── bytes__getitem_index_error.py
│ │ │ ├── bytes__index_start_gt_end.py
│ │ │ ├── bytes__methods.py
│ │ │ ├── bytes__negative_count.py
│ │ │ ├── bytes__ops.py
│ │ │ ├── bytes__startswith_str_error.py
│ │ │ ├── call_object.py
│ │ │ ├── chain_comparison__all.py
│ │ │ ├── closure__param_shadows_outer.py
│ │ │ ├── closure__pep448.py
│ │ │ ├── closure__undefined_nonlocal.py
│ │ │ ├── compare__mixed_types.py
│ │ │ ├── comprehension__all.py
│ │ │ ├── comprehension__scope.py
│ │ │ ├── comprehension__unbound_local.py
│ │ │ ├── dataclass__basic.py
│ │ │ ├── dataclass__call_field_error.py
│ │ │ ├── dataclass__frozen_set_error.py
│ │ │ ├── dataclass__get_missing_attr_error.py
│ │ │ ├── dict__get_unhashable_key.py
│ │ │ ├── dict__literal_unhashable_key.py
│ │ │ ├── dict__method_pop_missing_error.py
│ │ │ ├── dict__methods.py
│ │ │ ├── dict__ops.py
│ │ │ ├── dict__pop_unhashable_key.py
│ │ │ ├── dict__popitem_empty.py
│ │ │ ├── dict__subscript_missing_key.py
│ │ │ ├── dict__unhashable_dict_key.py
│ │ │ ├── dict__unhashable_list_key.py
│ │ │ ├── dict__unpack_type_error.py
│ │ │ ├── dict__views.py
│ │ │ ├── edge__all.py
│ │ │ ├── edge__float_int_mod.py
│ │ │ ├── edge__int_float_mod.py
│ │ │ ├── exc__args.py
│ │ │ ├── exc__str.py
│ │ │ ├── execute_ok__all.py
│ │ │ ├── execute_raise__error_instance_str.py
│ │ │ ├── execute_raise__error_no_args.py
│ │ │ ├── execute_raise__error_string_arg.py
│ │ │ ├── execute_raise__error_string_arg_quotes.py
│ │ │ ├── execute_raise__error_type.py
│ │ │ ├── execute_raise__raise_instance_via_var.py
│ │ │ ├── execute_raise__raise_list.py
│ │ │ ├── execute_raise__raise_number.py
│ │ │ ├── execute_raise__raise_type_call_via_var.py
│ │ │ ├── execute_raise__raise_type_direct.py
│ │ │ ├── execute_raise__raise_type_via_var.py
│ │ │ ├── ext_call__arg_side_effect_bug.py
│ │ │ ├── ext_call__augmented.py
│ │ │ ├── ext_call__augmented_refcount_bug.py
│ │ │ ├── ext_call__bare_raise_after_resume.py
│ │ │ ├── ext_call__basic.py
│ │ │ ├── ext_call__boolean.py
│ │ │ ├── ext_call__boolean_side_effect_hang.py
│ │ │ ├── ext_call__closure_bug.py
│ │ │ ├── ext_call__comparison.py
│ │ │ ├── ext_call__deep_call_stack.py
│ │ │ ├── ext_call__elif.py
│ │ │ ├── ext_call__exc.py
│ │ │ ├── ext_call__exc_deep_stack.py
│ │ │ ├── ext_call__exc_in_function.py
│ │ │ ├── ext_call__exc_nested_functions.py
│ │ │ ├── ext_call__ext_exc.py
│ │ │ ├── ext_call__for.py
│ │ │ ├── ext_call__fstring.py
│ │ │ ├── ext_call__if.py
│ │ │ ├── ext_call__if_condition.py
│ │ │ ├── ext_call__in_closure.py
│ │ │ ├── ext_call__in_function.py
│ │ │ ├── ext_call__in_function_simple.py
│ │ │ ├── ext_call__literals.py
│ │ │ ├── ext_call__multi_in_func.py
│ │ │ ├── ext_call__name_lookup.py
│ │ │ ├── ext_call__name_lookup_undefined.py
│ │ │ ├── ext_call__nested_calls.py
│ │ │ ├── ext_call__recursion_bug.py
│ │ │ ├── ext_call__return.py
│ │ │ ├── ext_call__side_effects.py
│ │ │ ├── ext_call__subscript.py
│ │ │ ├── ext_call__ternary.py
│ │ │ ├── ext_call__try.py
│ │ │ ├── ext_call__try_simple.py
│ │ │ ├── ext_call__unary.py
│ │ │ ├── frozenset__ops.py
│ │ │ ├── fstring__all.py
│ │ │ ├── fstring__error_eq_align_on_str.py
│ │ │ ├── fstring__error_float_f_on_str.py
│ │ │ ├── fstring__error_int_d_on_float.py
│ │ │ ├── fstring__error_int_d_on_str.py
│ │ │ ├── fstring__error_invalid_spec.py
│ │ │ ├── fstring__error_invalid_spec_dynamic.py
│ │ │ ├── fstring__error_invalid_spec_str.py
│ │ │ ├── fstring__error_str_s_on_int.py
│ │ │ ├── function__call_duplicate_kwargs.py
│ │ │ ├── function__call_unpack.py
│ │ │ ├── function__defaults.py
│ │ │ ├── function__err_duplicate_arg.py
│ │ │ ├── function__err_duplicate_first_arg.py
│ │ │ ├── function__err_duplicate_kwarg_cleanup.py
│ │ │ ├── function__err_kwonly_as_positional.py
│ │ │ ├── function__err_missing_all_posonly.py
│ │ │ ├── function__err_missing_heap_cleanup.py
│ │ │ ├── function__err_missing_kwonly.py
│ │ │ ├── function__err_missing_posonly_with_kwarg.py
│ │ │ ├── function__err_missing_with_posonly.py
│ │ │ ├── function__err_posonly_as_kwarg.py
│ │ │ ├── function__err_posonly_first_as_kwarg.py
│ │ │ ├── function__err_too_many_posonly.py
│ │ │ ├── function__err_too_many_with_kwonly.py
│ │ │ ├── function__err_unexpected_kwarg.py
│ │ │ ├── function__err_unexpected_kwarg_cleanup.py
│ │ │ ├── function__err_unexpected_kwarg_quote.py
│ │ │ ├── function__err_unexpected_kwarg_simple.py
│ │ │ ├── function__err_unpack_duplicate_arg.py
│ │ │ ├── function__err_unpack_duplicate_heap.py
│ │ │ ├── function__err_unpack_int.py
│ │ │ ├── function__err_unpack_nonstring_key.py
│ │ │ ├── function__err_unpack_not_mapping.py
│ │ │ ├── function__kwargs_unpacking.py
│ │ │ ├── function__ops.py
│ │ │ ├── function__return_none.py
│ │ │ ├── function__signatures.py
│ │ │ ├── function__too_few_args_all.py
│ │ │ ├── function__too_few_args_one.py
│ │ │ ├── function__too_few_args_two.py
│ │ │ ├── function__too_many_args_one.py
│ │ │ ├── function__too_many_args_two.py
│ │ │ ├── function__too_many_args_zero.py
│ │ │ ├── global__error_assigned_before.py
│ │ │ ├── global__ops.py
│ │ │ ├── hash__dict_unhashable.py
│ │ │ ├── hash__list_unhashable.py
│ │ │ ├── hash__ops.py
│ │ │ ├── id__bytes_literals_distinct.py
│ │ │ ├── id__int_copy_distinct.py
│ │ │ ├── id__is_number_is_number.py
│ │ │ ├── id__non_overlapping_lifetimes_distinct_types.py
│ │ │ ├── id__non_overlapping_lifetimes_same_types.py
│ │ │ ├── id__ops.py
│ │ │ ├── id__str_literals_same.py
│ │ │ ├── if__elif_else.py
│ │ │ ├── if__raise_elif.py
│ │ │ ├── if__raise_else.py
│ │ │ ├── if__raise_if.py
│ │ │ ├── if__raise_in_elif_condition.py
│ │ │ ├── if__raise_in_if_condition.py
│ │ │ ├── if_else_expr__all.py
│ │ │ ├── import__error_cannot_import.py
│ │ │ ├── import__error_module_not_found.py
│ │ │ ├── import__local_scope.py
│ │ │ ├── import__os.py
│ │ │ ├── import__relative_error.py
│ │ │ ├── import__relative_no_module_error.py
│ │ │ ├── import__runtime_error_when_executed.py
│ │ │ ├── import__star_error.py
│ │ │ ├── import__sys.py
│ │ │ ├── import__sys_monty.py
│ │ │ ├── import__type_checking_guard.py
│ │ │ ├── import__typing.py
│ │ │ ├── import__typing_type_ignore.py
│ │ │ ├── int__bigint.py
│ │ │ ├── int__bigint_errors.py
│ │ │ ├── int__ops.py
│ │ │ ├── int__overflow_division.py
│ │ │ ├── is_variant__all.py
│ │ │ ├── isinstance__arg2_list_error.py
│ │ │ ├── isinstance__arg2_type_error.py
│ │ │ ├── iter__dict_mutation.py
│ │ │ ├── iter__for.py
│ │ │ ├── iter__for_loop_unpacking.py
│ │ │ ├── iter__generator_expr.py
│ │ │ ├── iter__generator_expr_type.py
│ │ │ ├── iter__not_iterable.py
│ │ │ ├── lambda__all.py
│ │ │ ├── list__extend_not_iterable.py
│ │ │ ├── list__getitem_out_of_bounds.py
│ │ │ ├── list__index_not_found.py
│ │ │ ├── list__index_start_gt_end.py
│ │ │ ├── list__ops.py
│ │ │ ├── list__pop_empty.py
│ │ │ ├── list__pop_out_of_range.py
│ │ │ ├── list__pop_type_error.py
│ │ │ ├── list__remove_not_found.py
│ │ │ ├── list__setitem_dict_index.py
│ │ │ ├── list__setitem_huge_int_index.py
│ │ │ ├── list__setitem_index_error.py
│ │ │ ├── list__setitem_type_error.py
│ │ │ ├── list__unpack_type_error.py
│ │ │ ├── longint__index_error.py
│ │ │ ├── longint__repeat_error.py
│ │ │ ├── loop__break_continue.py
│ │ │ ├── loop__break_finally.py
│ │ │ ├── loop__break_in_function_error.py
│ │ │ ├── loop__break_in_if_error.py
│ │ │ ├── loop__break_nested_except_clears.py
│ │ │ ├── loop__break_outside_error.py
│ │ │ ├── loop__continue_finally.py
│ │ │ ├── loop__continue_in_function_error.py
│ │ │ ├── loop__continue_in_if_error.py
│ │ │ ├── loop__continue_nested_except_clears.py
│ │ │ ├── loop__continue_outside_error.py
│ │ │ ├── math__acos_domain_error.py
│ │ │ ├── math__acosh_domain_error.py
│ │ │ ├── math__asin_domain_error.py
│ │ │ ├── math__atanh_domain_error.py
│ │ │ ├── math__cos_inf_error.py
│ │ │ ├── math__cosh_overflow_error.py
│ │ │ ├── math__exp_overflow_error.py
│ │ │ ├── math__factorial_float_error.py
│ │ │ ├── math__factorial_negative_error.py
│ │ │ ├── math__floor_inf_error.py
│ │ │ ├── math__floor_nan_error.py
│ │ │ ├── math__floor_str_error.py
│ │ │ ├── math__fmod_inf_error.py
│ │ │ ├── math__gamma_neg_int_error.py
│ │ │ ├── math__gcd_float_error.py
│ │ │ ├── math__isqrt_negative_error.py
│ │ │ ├── math__ldexp_overflow_error.py
│ │ │ ├── math__log1p_domain_error.py
│ │ │ ├── math__log_base1_error.py
│ │ │ ├── math__log_zero_error.py
│ │ │ ├── math__module.py
│ │ │ ├── math__pow_domain_error.py
│ │ │ ├── math__sin_inf_error.py
│ │ │ ├── math__sqrt_negative_error.py
│ │ │ ├── math__tan_inf_error.py
│ │ │ ├── math__trunc_str_error.py
│ │ │ ├── method__args_kwargs_unpacking.py
│ │ │ ├── name_error__unbound_local_func.py
│ │ │ ├── name_error__unbound_local_module.py
│ │ │ ├── name_error__undefined_call_chained.py
│ │ │ ├── name_error__undefined_call_in_expr.py
│ │ │ ├── name_error__undefined_call_in_function.py
│ │ │ ├── name_error__undefined_call_with_args.py
│ │ │ ├── name_error__undefined_global.py
│ │ │ ├── namedtuple__missing_attr.py
│ │ │ ├── namedtuple__ops.py
│ │ │ ├── nonlocal__error_module_level.py
│ │ │ ├── nonlocal__ops.py
│ │ │ ├── os__environ.py
│ │ │ ├── os__getenv_key_list_error.py
│ │ │ ├── os__getenv_key_type_error.py
│ │ │ ├── parse_error__complex.py
│ │ │ ├── pathlib__import.py
│ │ │ ├── pathlib__os.py
│ │ │ ├── pathlib__os_read_error.py
│ │ │ ├── pathlib__pure.py
│ │ │ ├── pyobject__cycle_dict_self.py
│ │ │ ├── pyobject__cycle_list_dict.py
│ │ │ ├── pyobject__cycle_list_self.py
│ │ │ ├── pyobject__cycle_multiple_refs.py
│ │ │ ├── range__error_no_args.py
│ │ │ ├── range__error_step_zero.py
│ │ │ ├── range__error_too_many_args.py
│ │ │ ├── range__getitem_index_error.py
│ │ │ ├── range__ops.py
│ │ │ ├── re__basic.py
│ │ │ ├── re__grouping.py
│ │ │ ├── re__match.py
│ │ │ ├── recursion__deep_drop.py
│ │ │ ├── recursion__deep_eq.py
│ │ │ ├── recursion__deep_hash.py
│ │ │ ├── recursion__deep_repr.py
│ │ │ ├── recursion__function_depth.py
│ │ │ ├── refcount__cycle_mutual_reference.py
│ │ │ ├── refcount__cycle_self_reference.py
│ │ │ ├── refcount__dict_basic.py
│ │ │ ├── refcount__dict_get.py
│ │ │ ├── refcount__dict_keys_and.py
│ │ │ ├── refcount__dict_overwrite.py
│ │ │ ├── refcount__gather_cleanup.py
│ │ │ ├── refcount__gather_exception.py
│ │ │ ├── refcount__gather_nested_cancel.py
│ │ │ ├── refcount__immediate_skipped.py
│ │ │ ├── refcount__keyword_only_kwarg_arity_errors.py
│ │ │ ├── refcount__kwargs_unpacking.py
│ │ │ ├── refcount__list_append_multiple.py
│ │ │ ├── refcount__list_append_ref.py
│ │ │ ├── refcount__list_concat.py
│ │ │ ├── refcount__list_getitem.py
│ │ │ ├── refcount__list_iadd.py
│ │ │ ├── refcount__min_max_key_error_paths.py
│ │ │ ├── refcount__nested_list.py
│ │ │ ├── refcount__re_pattern_sub_error_paths.py
│ │ │ ├── refcount__re_search_match.py
│ │ │ ├── refcount__re_sub_error_paths.py
│ │ │ ├── refcount__shared_reference.py
│ │ │ ├── refcount__single_list.py
│ │ │ ├── repr__cycle_detection.py
│ │ │ ├── set__ops.py
│ │ │ ├── set__review_bugs.py
│ │ │ ├── set__unpack_type_error.py
│ │ │ ├── slice__invalid_indices.py
│ │ │ ├── slice__kwargs.py
│ │ │ ├── slice__no_args.py
│ │ │ ├── slice__ops.py
│ │ │ ├── slice__step_zero.py
│ │ │ ├── slice__step_zero_bytes.py
│ │ │ ├── slice__step_zero_range.py
│ │ │ ├── slice__step_zero_str.py
│ │ │ ├── slice__step_zero_tuple.py
│ │ │ ├── slice__too_many_args.py
│ │ │ ├── str__getitem_index_error.py
│ │ │ ├── str__index_not_found.py
│ │ │ ├── str__join_no_args.py
│ │ │ ├── str__join_non_string.py
│ │ │ ├── str__join_not_iterable.py
│ │ │ ├── str__join_too_many_args.py
│ │ │ ├── str__methods.py
│ │ │ ├── str__ops.py
│ │ │ ├── str__partition_empty.py
│ │ │ ├── str__rsplit_empty_sep.py
│ │ │ ├── str__split_empty_sep.py
│ │ │ ├── sys__types.py
│ │ │ ├── traceback__division_error.py
│ │ │ ├── traceback__index_error.py
│ │ │ ├── traceback__insert_as_int.py
│ │ │ ├── traceback__nested_call.py
│ │ │ ├── traceback__nonlocal_module_scope.py
│ │ │ ├── traceback__nonlocal_unbound.py
│ │ │ ├── traceback__range_as_int.py
│ │ │ ├── traceback__recursion_error.py
│ │ │ ├── traceback__set_mutation.py
│ │ │ ├── traceback__undefined_attr_call.py
│ │ │ ├── traceback__undefined_call.py
│ │ │ ├── traceback__undefined_raise.py
│ │ │ ├── try_except__all.py
│ │ │ ├── try_except__bare_raise_no_context.py
│ │ │ ├── try_except__invalid_type.py
│ │ │ ├── tuple__getitem_out_of_bounds.py
│ │ │ ├── tuple__index_not_found.py
│ │ │ ├── tuple__index_start_gt_end.py
│ │ │ ├── tuple__methods.py
│ │ │ ├── tuple__ops.py
│ │ │ ├── tuple__unpack_type_error.py
│ │ │ ├── type__builtin_attr_error.py
│ │ │ ├── type__bytes_negative.py
│ │ │ ├── type__cell_not_builtin.py
│ │ │ ├── type__exception_attr_error.py
│ │ │ ├── type__float_conversion_error.py
│ │ │ ├── type__float_repr_both_quotes.py
│ │ │ ├── type__float_repr_newline.py
│ │ │ ├── type__float_repr_single_quote.py
│ │ │ ├── type__int_conversion_error.py
│ │ │ ├── type__list_not_iterable.py
│ │ │ ├── type__non_builtin_name_error.py
│ │ │ ├── type__ops.py
│ │ │ ├── type__shadow_exc.py
│ │ │ ├── type__shadow_int.py
│ │ │ ├── type__shadow_len.py
│ │ │ ├── type__tuple_not_iterable.py
│ │ │ ├── type_error__int_add_list.py
│ │ │ ├── type_error__int_div_str.py
│ │ │ ├── type_error__int_floordiv_str.py
│ │ │ ├── type_error__int_iadd_str.py
│ │ │ ├── type_error__int_mod_str.py
│ │ │ ├── type_error__int_pow_str.py
│ │ │ ├── type_error__int_sub_str.py
│ │ │ ├── type_error__list_add_int.py
│ │ │ ├── type_error__list_add_str.py
│ │ │ ├── type_error__list_iadd_int.py
│ │ │ ├── type_error__str_add_int.py
│ │ │ ├── type_error__str_iadd_int.py
│ │ │ ├── type_error__unary_invert_str.py
│ │ │ ├── type_error__unary_minus_str.py
│ │ │ ├── type_error__unary_neg_str.py
│ │ │ ├── type_error__unary_plus_str.py
│ │ │ ├── typing__types.py
│ │ │ ├── unpack__nested.py
│ │ │ ├── unpack__non_sequence.py
│ │ │ ├── unpack__not_enough.py
│ │ │ ├── unpack__ops.py
│ │ │ ├── unpack__star_not_enough.py
│ │ │ ├── unpack__too_many.py
│ │ │ ├── version__cpython.py
│ │ │ ├── walrus__all.py
│ │ │ └── while__all.py
│ │ └── tests/
│ │ ├── asyncio.rs
│ │ ├── binary_serde.rs
│ │ ├── bytecode_limits.rs
│ │ ├── datatest_runner.rs
│ │ ├── inputs.rs
│ │ ├── json_serde.rs
│ │ ├── main.rs
│ │ ├── math_module.rs
│ │ ├── name_lookup.rs
│ │ ├── os_tests.rs
│ │ ├── parse_errors.rs
│ │ ├── print_writer.rs
│ │ ├── py_object.rs
│ │ ├── regex.rs
│ │ ├── repl.rs
│ │ ├── resource_limits.rs
│ │ └── try_from.rs
│ ├── monty-cli/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── monty-js/
│ │ ├── .cargo/
│ │ │ └── config.toml
│ │ ├── .gitignore
│ │ ├── .prettierignore
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── __test__/
│ │ │ ├── async.spec.ts
│ │ │ ├── basic.spec.ts
│ │ │ ├── exceptions.spec.ts
│ │ │ ├── external.spec.ts
│ │ │ ├── inputs.spec.ts
│ │ │ ├── limits.spec.ts
│ │ │ ├── package.json
│ │ │ ├── print.spec.ts
│ │ │ ├── repl.spec.ts
│ │ │ ├── serialize.spec.ts
│ │ │ ├── start.spec.ts
│ │ │ ├── type_check.spec.ts
│ │ │ └── types.spec.ts
│ │ ├── build.rs
│ │ ├── index-header.d.ts
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── smoke-test.sh
│ │ ├── smoke-test/
│ │ │ ├── .gitignore
│ │ │ ├── package.json
│ │ │ ├── test.ts
│ │ │ └── tsconfig.json
│ │ ├── src/
│ │ │ ├── convert.rs
│ │ │ ├── exceptions.rs
│ │ │ ├── lib.rs
│ │ │ ├── limits.rs
│ │ │ └── monty_cls.rs
│ │ ├── tsconfig.json
│ │ └── wrapper.ts
│ ├── monty-python/
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── build.rs
│ │ ├── example.py
│ │ ├── exercise.py
│ │ ├── pyproject.toml
│ │ ├── python/
│ │ │ └── pydantic_monty/
│ │ │ ├── __init__.py
│ │ │ ├── _monty.pyi
│ │ │ ├── os_access.py
│ │ │ └── py.typed
│ │ ├── src/
│ │ │ ├── convert.rs
│ │ │ ├── dataclass.rs
│ │ │ ├── exceptions.rs
│ │ │ ├── external.rs
│ │ │ ├── lib.rs
│ │ │ ├── limits.rs
│ │ │ ├── monty_cls.rs
│ │ │ ├── repl.rs
│ │ │ └── serialization.rs
│ │ └── tests/
│ │ ├── test_async.py
│ │ ├── test_basic.py
│ │ ├── test_dataclasses.py
│ │ ├── test_exceptions.py
│ │ ├── test_external.py
│ │ ├── test_inputs.py
│ │ ├── test_limits.py
│ │ ├── test_os_access.py
│ │ ├── test_os_access_compat.py
│ │ ├── test_os_access_raw.py
│ │ ├── test_os_calls.py
│ │ ├── test_print.py
│ │ ├── test_re.py
│ │ ├── test_readme_examples.py
│ │ ├── test_repl.py
│ │ ├── test_serialize.py
│ │ ├── test_start.py
│ │ ├── test_threading.py
│ │ ├── test_type_check.py
│ │ └── test_types.py
│ ├── monty-type-checking/
│ │ ├── Cargo.toml
│ │ ├── src/
│ │ │ ├── db.rs
│ │ │ ├── lib.rs
│ │ │ └── type_check.rs
│ │ └── tests/
│ │ ├── bad_types.py
│ │ ├── bad_types_output.txt
│ │ ├── good_types.py
│ │ ├── main.rs
│ │ ├── reveal_types.py
│ │ └── reveal_types_output.txt
│ └── monty-typeshed/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── README.md
│ ├── build.rs
│ ├── custom/
│ │ ├── README.md
│ │ ├── asyncio.pyi
│ │ ├── os.pyi
│ │ └── sys.pyi
│ ├── src/
│ │ └── lib.rs
│ ├── update.py
│ └── vendor/
│ └── typeshed/
│ ├── source_commit.txt
│ └── stdlib/
│ ├── VERSIONS
│ ├── _collections_abc.pyi
│ ├── _typeshed/
│ │ └── __init__.pyi
│ ├── asyncio.pyi
│ ├── builtins.pyi
│ ├── collections/
│ │ ├── __init__.pyi
│ │ └── abc.pyi
│ ├── dataclasses.pyi
│ ├── enum.pyi
│ ├── math.pyi
│ ├── os.pyi
│ ├── pathlib/
│ │ ├── __init__.pyi
│ │ └── types.pyi
│ ├── re.pyi
│ ├── sys.pyi
│ ├── types.pyi
│ ├── typing.pyi
│ └── typing_extensions.pyi
├── examples/
│ ├── README.md
│ ├── expense_analysis/
│ │ ├── README.md
│ │ ├── data.py
│ │ └── main.py
│ ├── sql_playground/
│ │ ├── README.md
│ │ ├── external_functions.py
│ │ ├── main.py
│ │ ├── sandbox_code.py
│ │ └── type_stubs.pyi
│ └── web_scraper/
│ ├── README.md
│ ├── browser.py
│ ├── example_code.py
│ ├── external_functions.py
│ ├── main.py
│ └── sub_agent.py
├── pyproject.toml
└── scripts/
├── check_imports.py
├── codecov_diff.py
├── complete_tests.py
├── flamegraph_to_text.py
├── iter_test_methods.py
├── run_traceback.py
└── startup_performance.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .cargo/config.toml
================================================
[env]
# Use the project's venv Python for PyO3 builds
PYO3_PYTHON = { value = ".venv/bin/python3", relative = true }
================================================
FILE: .claude/settings.json
================================================
{
"permissions": {
"allow": [
"Bash(cargo:*)",
"Bash(timeout 30s cargo:*)",
"Bash(timeout 10s cargo:*)",
"Bash(timeout 15s cargo:*)",
"Bash(RUST_BACKTRACE=1 cargo:*)",
"Bash(make:*)",
"Bash(INLINE_SNAPSHOT_DEFAULT_FLAGS=disable make:*)",
"Bash(mkdir:*)",
"Bash(uv:*)",
"Bash(echo:*)",
"Bash(rg:*)",
"Bash(sed:*)",
"Bash(grep:*)",
"Bash(fastmod:*)",
"Bash(find:*)",
"Bash(ls:*)",
"Bash(cat:*)",
"Bash(python3:*)",
"Bash(git show:*)",
"Bash(git diff:*)",
"Bash(git add:*)",
"Bash(git stash:*)",
"Bash(git checkout:*)",
"Bash(git mv:*)",
"Bash(git log:*)",
"Bash(git grep:*)",
"Bash(git status:*)",
"Bash(gh pr view:*)",
"Bash(gh api:*)",
"Bash(gh run view:*)",
"Bash(gh issue view:*)",
"Skill(python-playground)",
"Skill(fastmod)",
"Skill(coverage)",
"Bash(wc:*)",
"Bash(xxd:*)",
"Bash(head:*)",
"Bash(rustup show:*)",
"Bash(xargs:*)",
"Bash(perl:*)",
"Bash(du:*)",
"Bash(npm run:*)",
"Bash(mkdir:*)",
"WebSearch",
"WebFetch(domain:pypi.org)",
"WebFetch(domain:docs.anthropic.com)",
"WebFetch(domain:github.com)",
"WebFetch(domain:15r10nk.github.io)",
"WebFetch(domain:docs.rs)",
"WebFetch(domain:pyo3.rs)",
"WebFetch(domain:napi.rs)",
"WebFetch(domain:app.codecov.io)"
],
"deny": [],
"ask": []
}
}
================================================
FILE: .claude/skills/coverage/SKILL.md
================================================
---
name: coverage
description: Fetch coverage diff from Codecov for the current branch or a specific PR. Shows uncovered lines, patch coverage, and overall coverage change.
---
# Coverage
Fetch line-by-line coverage information from Codecov for a GitHub pull request.
## Instructions
Use this skill to check code coverage for your changes before merging.
### Current branch (auto-detect PR)
```bash
uv run scripts/codecov_diff.py
```
This auto-detects the org, repo, and PR number using the `gh` CLI based on the current branch.
### Specific PR number
```bash
uv run scripts/codecov_diff.py 123
```
## Output
The script outputs:
- PR title and state
- HEAD coverage (overall coverage on the branch)
- Patch coverage (coverage of changed lines only)
- Coverage change (+/- percentage)
- Per-file breakdown with:
- Missed line count
- Patch coverage percentage
- Specific uncovered line numbers (as ranges like `45-48, 52, 60-65`)
- Partial coverage line numbers
## Requirements
- The `gh` CLI must be installed and authenticated for auto-detection
- The PR must have Codecov coverage data uploaded
================================================
FILE: .claude/skills/fastmod/SKILL.md
================================================
---
name: fastmod
description: Use fastmod to make mass code updates to avoid many repetitive changes.
---
# fastmod
## Instructions
You can occasionally use `fastmod` or `sed` to make mass updates to the codebase and avoid wasting tokens changing each case one at a time.
Before making many repetitive changes to the codebase, consider using `fastmod --accept-all`.
THINK HARD about how best to use `fastmod` as it can dramatically improve your productivity.
## Examples
Example of switching the `py_type` function to use `impl ResourceTracker` instead of `T: ResourceTracker`:
```bash
fastmod --accept-all 'fn py_type<T: ResourceTracker>(\(.+?)<T>' 'fn py_type$1<impl ResourceTracker>'
```
================================================
FILE: .claude/skills/python-playground/SKILL.md
================================================
---
name: python-playground
description: Run and test Python code in a dedicated playground directory. Use when you need to execute Python scripts, test code snippets, investigate CPython behavior, or experiment with Python without affecting the main codebase.
---
# Python Playground
Run Python code in an isolated playground directory for testing and experimentation.
## Instructions
1. First, ensure the playground directory exists: `mkdir -p playground`
2. Use the Write tool to create the Python file at `playground/test.py`
3. Run with: `uv run playground/test.py` to test cpython behavior or `cargo run -- playground/test.py` to test monty behavior
IMPORTANT: Use separate tool calls for each step - do NOT chain commands with `&&` or use heredocs. This allows the pre-approved commands to work without prompting.
## Example workflow
Step 1 - Create directory (Bash, already allowed):
```bash
mkdir -p playground
```
Step 2 - Write code (use Write tool, not cat):
Write to `playground/test.py`:
```python
def foo():
raise ValueError('test')
foo()
```
Step 3 - Run script (Bash, already allowed):
```bash
uv run playground/test.py
```
## Guidelines
- The `playground/` directory is gitignored
- Use a different file name for each test you want to run, give the files recognizable names like `test_value_error.py`
- Use `uv run ...` to run scripts (uses project Python)
- Or, `cargo run -- ...` to run scripts using Monty
- Use Write tool for creating files (avoids permission prompts)
- Run mkdir and uv as separate commands (not chained)
- do NOT delete files from playground after you've finished testing
================================================
FILE: .codecov.yml
================================================
codecov:
require_ci_to_pass: false
coverage:
precision: 2
# range: [90, 100]
status:
patch: false
project: false
comment:
layout: 'header, diff, flags, files, footer'
================================================
FILE: .github/actions/build-pgo-wheel/action.yml
================================================
name: Build PGO wheel
description: Builds a PGO-optimized wheel for pydantic-monty
inputs:
interpreter:
description: 'Interpreter(s) to build the wheel for'
required: true
rust-toolchain:
description: 'Rust toolchain to use'
required: true
outputs:
wheel-dir:
description: 'Path to the directory containing built wheels'
value: ${{ steps.find_wheel.outputs.dir }}
runs:
using: "composite"
steps:
- name: prepare profiling directory
shell: bash
run: mkdir -p ${{ github.workspace }}/profdata
- name: build initial wheel (instrumented)
uses: PyO3/maturin-action@v1
with:
manylinux: auto
args: >
--release
--out pgo-wheel
--interpreter 3.12
rust-toolchain: ${{ inputs.rust-toolchain }}
docker-options: -e CI
working-directory: crates/monty-python
env:
RUSTFLAGS: '-Cprofile-generate=${{ github.workspace }}/profdata'
- name: detect rust host
run: echo RUST_HOST=$(rustc -Vv | grep host | cut -d ' ' -f 2) >> "$GITHUB_ENV"
shell: bash
- name: generate pgo data
run: |
pip install pydantic-monty --no-index --no-deps --find-links pgo-wheel --force-reinstall
python exercise.py
rustup run ${{ inputs.rust-toolchain }} bash -c 'echo LLVM_PROFDATA=$RUSTUP_HOME/toolchains/$RUSTUP_TOOLCHAIN/lib/rustlib/$RUST_HOST/bin/llvm-profdata >> "$GITHUB_ENV"'
shell: bash
working-directory: crates/monty-python
- name: merge pgo data
# PowerShell handles paths on Windows better, and works well enough on Unix
run: ${{ env.LLVM_PROFDATA }} merge -o ${{ github.workspace }}/merged.profdata ${{ github.workspace }}/profdata
shell: pwsh
- name: build pgo-optimized wheel
uses: PyO3/maturin-action@v1
with:
manylinux: auto
args: >
--release
--out dist
--interpreter ${{ inputs.interpreter }}
rust-toolchain: ${{ inputs.rust-toolchain }}
docker-options: -e CI
working-directory: crates/monty-python
env:
RUSTFLAGS: '-Cprofile-use=${{ github.workspace }}/merged.profdata'
- name: find built wheels
id: find_wheel
run: echo "dir=crates/monty-python/dist" >> "$GITHUB_OUTPUT"
shell: bash
================================================
FILE: .github/workflows/ci.yml
================================================
name: ci
on:
push:
branches:
- main
tags:
- "**"
pull_request: {}
workflow_dispatch:
inputs:
run_release:
description: "Run release jobs (for manual tag releases)"
type: boolean
default: false
env:
COLUMNS: 150
UV_PYTHON: "3.14"
UV_FROZEN: "1"
DEBUG: "napi:*"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
prefix-key: "v1-rust"
- uses: astral-sh/setup-uv@v7
- run: uv sync --all-packages --only-dev
- uses: actions/cache@v5
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.UV_PYTHON }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: Setup node
uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: crates/monty-js/package-lock.json
- name: Install dependencies
run: npm install
working-directory: crates/monty-js
- run: uvx pre-commit run --color=always --all-files --verbose
env:
SKIP: no-commit-to-branch
- name: Show diff on failure
if: failure()
run: git diff
test-rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- uses: taiki-e/install-action@cargo-llvm-cov
# this means pyo3 will use Python 3.14 in tests
- uses: actions/setup-python@v6
with:
python-version: "3.14"
- run: rustc --version --verbose
- run: python3 -V
# don't use .venv python in CI
- run: rm .cargo/config.toml
# coverage for `make test-no-features`
- run: cargo llvm-cov --no-report -p monty
# coverage for `make test-ref-count-panic`
- run: cargo llvm-cov --no-report -p monty --features ref-count-panic
# coverage for `make test-ref-count-return`
- run: cargo llvm-cov --no-report -p monty --features ref-count-return
# coverage for `make test-type-checking`
- run: cargo llvm-cov --no-report -p monty_type_checking -p monty_typeshed
# Generating text report:
- run: cargo llvm-cov report --ignore-filename-regex '(tests/|test_cases/|/tests\.rs$$)'
# Generate codecov report (use `report` subcommand to avoid recompilation)
- run: cargo llvm-cov report --codecov --output-path=codecov.json --ignore-filename-regex '(tests/|test_cases/|/tests\.rs$$)'
- uses: codecov/codecov-action@v5
with:
files: codecov.json
token: ${{ secrets.CODECOV_TOKEN }}
test-python:
name: test python ${{ matrix.python-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
env:
UV_PYTHON: ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- uses: astral-sh/setup-uv@v7
- run: uv sync --all-packages --only-dev
- run: make dev-py
- run: make pytest
# also test with a release build
- run: make dev-py-release
- run: make pytest
# test uv run exercise script
- run: uv run crates/monty-python/exercise.py
bench-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- uses: actions/setup-python@v6
with:
python-version: "3.14"
# don't use .venv python in CI
- run: rm .cargo/config.toml
- run: make dev-bench
fuzz:
name: fuzz ${{ matrix.target }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target:
- tokens_input_panic
# disable until https://github.com/astral-sh/ruff/issues/23198 is fixed
# - string_input_panic
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- id: cache-rust
uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
prefix-key: "v1-rust-fuzz"
workspaces: "crates/fuzz -> target"
- if: steps.cache-rust.outputs.cache-hit != 'true'
run: cargo install cargo-fuzz
# don't use .venv python in CI
- run: rm .cargo/config.toml
- name: Run ${{ matrix.target }} fuzzer
run: |
# Use --sanitizer none to avoid ASAN/SanitizerCoverage linking issues on CI
# (undefined __sancov_gen_.* symbols). For short CI runs, we're mainly
# catching panics, not memory bugs.
cargo fuzz run --fuzz-dir crates/fuzz --sanitizer none ${{ matrix.target }} -- -max_total_time=60
# https://github.com/marketplace/actions/alls-green#why used for branch protection checks
check:
if: always()
needs:
- lint
- test-rust
- test-python
- bench-test
- fuzz
runs-on: ubuntu-latest
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
# Build source distribution
build-sdist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist
rust-toolchain: stable
working-directory: crates/monty-python
- uses: actions/upload-artifact@v6
with:
name: pypi_files-sdist
path: crates/monty-python/dist
# Build wheels for exotic architectures (non-PGO)
build:
name: build on ${{ matrix.os }} (${{ matrix.target }} - ${{ matrix.manylinux || 'auto' }})
# only run on push to main, on tags, or if 'Full Build' label is present
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'Full Build') || (github.event_name == 'workflow_dispatch' && inputs.run_release)
strategy:
fail-fast: false
matrix:
include:
# Linux aarch64
- os: linux
target: aarch64
# Linux i686
- os: linux
target: i686
# Linux armv7
- os: linux
target: armv7
# Linux ppc64le
- os: linux
target: ppc64le
# Linux s390x
- os: linux
target: s390x
# Linux x86_64 musl
- os: linux
target: x86_64
manylinux: musllinux_1_1
# Linux aarch64 musl
- os: linux
target: aarch64
manylinux: musllinux_1_1
# macOS x86_64 (Intel)
- os: macos
target: x86_64
# Windows i686
- os: windows
target: i686
runs-on: ${{ (matrix.os == 'linux' && 'ubuntu-latest') || (matrix.os == 'macos' && 'macos-latest') || (matrix.os == 'windows' && 'windows-latest') }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: ${{ matrix.manylinux || 'auto' }}
args: --release --out dist -i 3.10 3.11 3.12 3.13 3.14
rust-toolchain: stable
docker-options: -e CI
working-directory: crates/monty-python
- uses: actions/upload-artifact@v6
with:
name: pypi_files-${{ matrix.os }}-${{ matrix.target }}-${{ matrix.manylinux || 'manylinux' }}
path: crates/monty-python/dist
# PGO-optimized builds for main platforms
build-pgo:
name: build pgo on ${{ matrix.os }}
# only run on push to main, on tags, or if 'Full Build' label is present
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'Full Build') || (github.event_name == 'workflow_dispatch' && inputs.run_release)
strategy:
fail-fast: false
matrix:
include:
# Linux x86_64 (manylinux)
- os: linux
runs-on: ubuntu-latest
interpreter: 3.10 3.11 3.12 3.13 3.14
# Windows x86_64
- os: windows
runs-on: windows-latest
interpreter: 3.10 3.11 3.12 3.13 3.14
# macOS aarch64 (Apple Silicon)
- os: macos
runs-on: macos-latest
interpreter: 3.10 3.11 3.12 3.13 3.14
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools
- name: build PGO wheel
id: pgo
uses: ./.github/actions/build-pgo-wheel
with:
interpreter: ${{ matrix.interpreter }}
rust-toolchain: stable
- uses: actions/upload-artifact@v6
with:
name: pypi_files-${{ matrix.os }}-pgo
path: ${{ steps.pgo.outputs.wheel-dir }}
# Test wheels on exotic architectures via QEMU
test-builds-arch:
name: test build on ${{ matrix.target }}
needs: [build]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: [aarch64, armv7, s390x, ppc64le]
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v7
with:
pattern: pypi_files-linux-${{ matrix.target }}-*
merge-multiple: true
path: dist
- uses: uraimo/run-on-arch-action@v3
name: install & test
with:
arch: ${{ matrix.target }}
distro: ubuntu22.04
dockerRunArgs: --volume "${{ github.workspace }}/dist:/dist"
install: |
apt-get update
apt-get install -y --no-install-recommends python3 python3-pip python3-venv
run: |
ls -lh /dist/
python3 -m venv venv
source venv/bin/activate
python3 -m pip install pydantic-monty --no-index --no-deps --find-links /dist --force-reinstall
python3 -c "import pydantic_monty; print(pydantic_monty.Monty('1 + 2').run())"
# Test wheels on main OS platforms
test-builds-os:
name: test build on ${{ matrix.os }}
needs: [build, build-pgo]
runs-on: ${{ matrix.runs-on }}
strategy:
fail-fast: false
matrix:
include:
- os: linux
runs-on: ubuntu-latest
- os: macos
runs-on: macos-latest
- os: windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- uses: actions/download-artifact@v7
with:
pattern: pypi_files-${{ matrix.os }}-*
merge-multiple: true
path: dist
- run: pip install pydantic-monty --no-index --find-links dist --force-reinstall
- run: python -c "import pydantic_monty; print(pydantic_monty.Monty('1 + 2').run())"
# Inspect built artifacts
inspect-python-assets:
needs: [build, build-pgo, build-sdist]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v7
with:
pattern: pypi_files-*
merge-multiple: true
path: dist
- name: list files
run: |
ls -lhR dist/
ls -1 dist/ | wc -l
echo "Expected ~50 wheel files (5 Python versions × 10 platform variants)"
- uses: astral-sh/setup-uv@v7
- run: uvx twine check dist/*
# Release to PyPI
release-python:
name: release to PyPI
needs: [check, inspect-python-assets, test-builds-arch, test-builds-os]
if: success() && (startsWith(github.ref, 'refs/tags/') || (github.event_name == 'workflow_dispatch' && inputs.run_release))
runs-on: ubuntu-latest
environment:
name: release-python
url: https://pypi.org/project/pydantic-monty/${{ steps.check-version.outputs.VERSION }}
permissions:
id-token: write
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- uses: actions/download-artifact@v7
with:
pattern: pypi_files-*
merge-multiple: true
path: dist
- id: check-version
uses: samuelcolvin/check-python-version@v5
with:
version_file_path: "Cargo.toml"
- run: ls -lhR dist/
- name: Publish to PyPI
run: "uv publish --trusted-publishing always dist/*"
build-js:
name: build JS - ${{ matrix.settings.target }} - node@22
runs-on: ${{ matrix.settings.host }}
# only run on push to main, on tags, or if 'Full Build' label is present
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'Full Build') || (github.event_name == 'workflow_dispatch' && inputs.run_release)
strategy:
fail-fast: false
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
build: npm run build:napi -- --target x86_64-apple-darwin && npm run build:ts
- host: windows-latest
target: x86_64-pc-windows-msvc
build: npm run build:napi -- --target x86_64-pc-windows-msvc && npm run build:ts
- host: ubuntu-latest
target: x86_64-unknown-linux-gnu
build: npm run build:napi -- --target x86_64-unknown-linux-gnu --use-napi-cross && npm run build:ts
- host: macos-latest
target: aarch64-apple-darwin
build: npm run build:napi -- --target aarch64-apple-darwin && npm run build:ts
- host: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
build: npm run build:napi -- --target aarch64-unknown-linux-gnu && npm run build:ts
- host: ubuntu-latest
target: wasm32-wasip1-threads
build: npm run build:napi -- --target wasm32-wasip1-threads && npm run build:ts
steps:
- uses: actions/checkout@v6
- name: Setup node
uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: crates/monty-js/package-lock.json
- name: Install
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: ${{ matrix.settings.target }}
- name: Cache cargo
uses: actions/cache@v5
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
~/.napi-rs
.cargo-cache
target/
key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}
# don't use .venv python in CI
- run: rm .cargo/config.toml
- uses: mlugg/setup-zig@v2
if: ${{ contains(matrix.settings.target, 'musl') }}
with:
version: 0.14.1
- name: Install cargo-zigbuild
uses: taiki-e/install-action@v2
if: ${{ contains(matrix.settings.target, 'musl') }}
with:
tool: cargo-zigbuild
- name: Setup toolchain
run: ${{ matrix.settings.setup }}
if: ${{ matrix.settings.setup }}
shell: bash
- name: Install dependencies
run: npm install
working-directory: crates/monty-js
- name: Build
run: ${{ matrix.settings.build }}
shell: bash
working-directory: crates/monty-js
- name: Upload artifact
uses: actions/upload-artifact@v6
with:
name: js-bindings-${{ matrix.settings.target }}
path: |
crates/monty-js/monty.*.node
crates/monty-js/monty.*.wasm
if-no-files-found: error
# need to upload the .js files generated by napi; they are identical for whatever target
# so might as well upload from the linux job
- if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }}
name: Upload artifact
uses: actions/upload-artifact@v6
with:
name: js-stubs
path: |
crates/monty-js/browser.js
crates/monty-js/index.js
crates/monty-js/index.d.ts
crates/monty-js/wrapper.js
crates/monty-js/wrapper.d.ts
crates/monty-js/monty.wasi.cjs
crates/monty-js/monty.wasi-browser.js
crates/monty-js/wasi-worker.mjs
crates/monty-js/wasi-worker-browser.mjs
if-no-files-found: error
env:
MACOSX_DEPLOYMENT_TARGET: "10.13"
CARGO_INCREMENTAL: "1"
test-js-macOS-windows-binding:
name: Test JS bindings on ${{ matrix.settings.target }} - node@${{ matrix.node }}
needs:
- build-js
strategy:
fail-fast: false
matrix:
settings:
- host: windows-latest
target: x86_64-pc-windows-msvc
architecture: x64
- host: macos-latest
target: aarch64-apple-darwin
architecture: arm64
- host: macos-latest
target: x86_64-apple-darwin
architecture: x64
node:
- "20"
- "22"
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v6
- name: Setup node
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
cache: npm
cache-dependency-path: crates/monty-js/package-lock.json
architecture: ${{ matrix.settings.architecture }}
- name: Install dependencies
run: npm install
working-directory: crates/monty-js
- name: Download artifacts
uses: actions/download-artifact@v7
with:
name: js-bindings-${{ matrix.settings.target }}
path: crates/monty-js
- name: Download artifacts
uses: actions/download-artifact@v7
with:
name: js-stubs
path: crates/monty-js
- name: List packages
run: ls -R .
shell: bash
working-directory: crates/monty-js
- name: Test bindings
run: npm test
working-directory: crates/monty-js
test-js-linux-binding:
name: Test JS ${{ matrix.target }} - node@${{ matrix.node }}
needs:
- build-js
strategy:
fail-fast: false
matrix:
target:
- x86_64-unknown-linux-gnu
- aarch64-unknown-linux-gnu
node:
- "20"
- "22"
runs-on: ${{ contains(matrix.target, 'aarch64') && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v6
- name: Setup node
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
cache: npm
cache-dependency-path: crates/monty-js/package-lock.json
- name: Output docker params
id: docker
run: |
node -e "
if ('${{ matrix.target }}'.startsWith('aarch64')) {
console.log('PLATFORM=linux/arm64')
} else if ('${{ matrix.target }}'.startsWith('armv7')) {
console.log('PLATFORM=linux/arm/v7')
} else {
console.log('PLATFORM=linux/amd64')
}
" >> $GITHUB_OUTPUT
node -e "
if ('${{ matrix.target }}'.endsWith('-musl')) {
console.log('IMAGE=node:${{ matrix.node }}-alpine')
} else {
console.log('IMAGE=node:${{ matrix.node }}-slim')
}
" >> $GITHUB_OUTPUT
- name: Install dependencies
run: npm install
working-directory: crates/monty-js
- name: Download artifacts
uses: actions/download-artifact@v7
with:
name: js-bindings-${{ matrix.target }}
path: crates/monty-js
- name: Download artifacts
uses: actions/download-artifact@v7
with:
name: js-stubs
path: crates/monty-js
- name: List packages
run: ls -R .
shell: bash
working-directory: crates/monty-js
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
if: ${{ contains(matrix.target, 'armv7') }}
with:
platforms: all
- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
if: ${{ contains(matrix.target, 'armv7') }}
- name: Test bindings
run: >
docker run --rm -v ${{ github.workspace }}:${{ github.workspace }} -w ${{ github.workspace }}/crates/monty-js --platform ${{ steps.docker.outputs.PLATFORM }} ${{ steps.docker.outputs.IMAGE }} npm test
test-js-wasi:
name: Test WASI target
needs:
- build-js
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup node
uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: crates/monty-js/package-lock.json
- name: Install dependencies
run: npm install --cpu wasm32
working-directory: crates/monty-js
- name: Download artifacts
uses: actions/download-artifact@v7
with:
name: js-bindings-wasm32-wasip1-threads
path: crates/monty-js
- name: Download artifacts
uses: actions/download-artifact@v7
with:
name: js-stubs
path: crates/monty-js
- name: List packages
run: ls -R .
shell: bash
working-directory: crates/monty-js
- name: Test bindings
run: npm test
env:
NAPI_RS_FORCE_WASI: 1
working-directory: crates/monty-js
release-js:
name: Release to NPM
runs-on: ubuntu-latest
needs:
- check
- inspect-python-assets
- test-js-macOS-windows-binding
- test-js-linux-binding
- test-js-wasi
if: success() && (startsWith(github.ref, 'refs/tags/') || (github.event_name == 'workflow_dispatch' && inputs.run_release))
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v6
- name: Setup node
uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: crates/monty-js/package-lock.json
registry-url: "https://registry.npmjs.org"
- name: Install dependencies
run: npm install
working-directory: crates/monty-js
- name: create npm dirs
run: npm run create-npm-dirs
working-directory: crates/monty-js
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
pattern: js-bindings-*
path: crates/monty-js/artifacts
merge-multiple: true
- name: Download artifacts
uses: actions/download-artifact@v7
with:
name: js-stubs
path: crates/monty-js
- name: Move artifacts
run: npm run artifacts
working-directory: crates/monty-js
- name: List packages
run: ls -R ./npm
shell: bash
working-directory: crates/monty-js
- name: Publish
run: |
if [[ "$GITHUB_REF" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Publishing stable release"
npm publish --provenance --access public
else
echo "Publishing pre-release with 'next' tag"
npm publish --provenance --tag next --access public
fi
working-directory: crates/monty-js
================================================
FILE: .github/workflows/codspeed.yml
================================================
name: CodSpeed
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
permissions:
contents: read
id-token: write
jobs:
benchmarks:
name: Run benchmarks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- uses: actions/setup-python@v6
with:
python-version: "3.14"
- name: Remove .cargo config to use system Python
run: rm .cargo/config.toml
- name: Install cargo-codspeed
run: cargo install cargo-codspeed
- name: Build benchmarks
run: cargo codspeed build -p monty --bench main
- name: Run benchmarks
uses: CodSpeedHQ/action@v4
with:
mode: simulation
run: cargo codspeed run -p monty --bench main
================================================
FILE: .github/workflows/init-npm-packages.yml
================================================
name: Initialize NPM Platform Packages
# Creates placeholder packages on npm for any new napi platform targets.
# npm requires packages to exist before OIDC/provenance publishing can work,
# so this must be run once per new target before the first release that includes it.
#
# After running, configure Trusted Publishing on npmjs.com for each new package:
# Package Settings > Trusted Publisher > GitHub Actions > pydantic/monty
on:
workflow_dispatch: {}
jobs:
init-packages:
name: Initialize missing platform packages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
- name: Install dependencies
run: npm install
working-directory: crates/monty-js
- name: Create npm dirs
run: npm run create-npm-dirs
working-directory: crates/monty-js
- name: Check and create missing platform packages
working-directory: crates/monty-js
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
created=()
for pkg_dir in npm/*/; do
name=$(node -p "require('./${pkg_dir}package.json').name")
if npm view "$name" version > /dev/null 2>&1; then
echo "✓ $name already exists"
continue
fi
echo "Creating placeholder for $name..."
tmp=$(mktemp -d)
node -e "
const pkg = require('./${pkg_dir}package.json');
const placeholder = {
name: pkg.name,
version: '0.0.0',
description: 'Placeholder for OIDC trusted publishing setup — this version contains no code.',
license: pkg.license,
repository: pkg.repository,
publishConfig: pkg.publishConfig,
os: pkg.os,
cpu: pkg.cpu,
};
if (pkg.libc) placeholder.libc = pkg.libc;
require('fs').writeFileSync('${tmp}/package.json', JSON.stringify(placeholder, null, 2));
"
(cd "$tmp" && npm publish --access public)
rm -rf "$tmp"
created+=("$name")
echo "✓ Created $name@0.0.0"
done
echo ""
if [ ${#created[@]} -eq 0 ]; then
echo "All platform packages already exist on npm."
else
echo "Created ${#created[@]} new package(s):"
for name in "${created[@]}"; do
echo " - $name"
echo " Configure Trusted Publishing: https://www.npmjs.com/package/${name}/access"
done
echo ""
echo "⚠ You must configure Trusted Publishing for each new package on npmjs.com"
echo " before the next release will succeed with OIDC/provenance."
fi
================================================
FILE: .gitignore
================================================
*.py[cod]
*.so
/.idea/
/target/
/env*/
/*.py
/TODO.md
/monty
/.claude/settings.local.json
/scratch/
/worktrees/
/flame/
/playground/
/type-sizes.txt
/sandbox/
/starlark-rust/
/.playwright-mcp/
/crates/fuzz/artifacts/
/crates/fuzz/corpus/
/.worktrees/
/.zed/
================================================
FILE: .pre-commit-config.yaml
================================================
fail_fast: true
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: no-commit-to-branch # prevent direct commits to the `main` branch
- id: check-yaml
- id: check-toml
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-added-large-files
- repo: https://github.com/codespell-project/codespell
# Configuration for codespell is in pyproject.toml
rev: v2.3.0
hooks:
- id: codespell
additional_dependencies:
- tomli
- repo: local
hooks:
- id: format-rs
name: Format Rust
entry: make format-rs
types: [rust]
language: system
pass_filenames: false
- id: lint-rs
name: Lint Rust
entry: make lint-rs
types: [rust]
language: system
pass_filenames: false
- id: format-lint-py
name: Format & Lint Python
entry: make format-lint-py
types: [python]
language: system
pass_filenames: false
- id: format-lint-js
name: Format & Lint TypeScript
entry: make format-js lint-js
types: [ts]
language: system
pass_filenames: false
================================================
FILE: .python-version
================================================
3.14
================================================
FILE: .rustfmt.toml
================================================
max_width = 120
imports_granularity = "Crate"
group_imports = "StdExternalCrate"
reorder_imports = true
================================================
FILE: CLAUDE.md
================================================
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Monty is a sandboxed Python interpreter written in Rust. It parses Python code using Ruff's `ruff_python_parser` but implements its own runtime execution model for safety and performance. This is a work-in-progress project that currently supports a subset of Python features.
Project goals:
- **Safety**: Execute untrusted Python code safely without FFI or C dependencies, instead sandbox will call back to host to run foreign/external functions.
- **Performance**: Fast execution through compile-time optimizations and efficient memory layout
- **Simplicity**: Clean, understandable implementation focused on a Python subset
- **Snapshotting and iteration**: Plan is to allow code to be iteratively executed and snapshotted at each function call
- Targets the latest stable version of Python, currently Python 3.14
## Important Security Notice
It's ABSOLUTELY CRITICAL that there's no way for code run in a Monty sandbox to access the host filesystem, or environment or to in any way "escape the sandbox".
**Monty will be used to run untrusted, potentially malicious code.**
Make sure there's no risk of this, either in the implementation, or in the public API that makes it more like that a developer using the pydantic_monty package might make such a mistake.
Possible security risks to consider:
* filesystem access
* path traversal to access files the users did not intend to expose to the monty sandbox
* memory errors - use of unsafe memory operations
* excessive memory usage - evading monty's resource limits
* infinite loops - evading monty's resource limits
* network access - sockets, HTTP requests
* subprocess/shell execution - os.system, subprocess, etc.
* import system abuse - importing modules with side effects or accessing `__import__`
* external function/callback misuse - callbacks run in host environment
* deserialization attacks - loading untrusted serialized Monty/snapshot data
* regex/string DoS - catastrophic backtracking or operations bypassing limits
* information leakage via timing or error messages
* Python/Javascript/Rust APIs that accidentally allow developers to expose their host to monty code
## Bytecode VM Architecture
Monty is implemented as a bytecode VM, same as CPython.
### Reference Count Safety
All types that implement `DropWithHeap` hold heap references and **must** be cleaned up correctly on every code path — not just the happy path, but also early returns via `?`, `continue`, conditional branches, etc. A missed `drop_with_heap` on any branch leaks reference counts. There are three mechanisms for ensuring this, listed in order of preference:
#### 1. `defer_drop!` macro (preferred)
The simplest and safest approach. Use `defer_drop!` (or `defer_drop_mut!` when mutable access to the value is needed) to bind a value into a guard that automatically drops it when scope exits — whether that's normal completion, early return via `?`, `continue`, or any other branch. The macro rebinds the value and heap variables as borrows from the guard, so you keep using them by name as before:
```rust
let value = self.pop();
defer_drop!(value, heap); // value is now &Value, heap is now &mut Heap
let result = value.py_repr(heap)?; // guard handles cleanup on all paths
```
Beyond safety, `defer_drop!` is often much more concise than inserting `drop_with_heap` calls in every branch of complex control flow.
`defer_drop!` gives you an immutable reference to the value. Use `defer_drop_mut!` when you need a mutable reference (e.g. iterators, values you may swap):
```rust
let iter = vm.heap.get_iter(iter_ref);
defer_drop_mut!(iter, vm);
while let Some(item) = iter.for_next(vm)? { ... }
```
**Limitation:** because the macro rebinds the heap, it cannot be used inside `&mut self` methods where `self` owns the heap — first assign `let this = self;` and pass `this` instead.
#### 2. `HeapGuard` (when you need control over the value's fate)
Use `HeapGuard` directly when `defer_drop!` is too restrictive — specifically when you need to conditionally extract the value instead of dropping it. `HeapGuard` provides `into_inner()` and `into_parts()` to reclaim ownership, while its `Drop` impl still guarantees cleanup on all other paths:
```rust
// HeapGuard needed here because on success we push lhs back onto the stack
// instead of dropping it
let mut lhs_guard = HeapGuard::new(self.pop(), self);
let (lhs, this) = lhs_guard.as_parts_mut();
if lhs.py_iadd(rhs, this.heap)? {
let (lhs, this) = lhs_guard.into_parts(); // reclaim lhs, don't drop
this.push(lhs);
return Ok(());
}
// otherwise lhs_guard drops lhs automatically at scope exit
```
#### 3. Manual `drop_with_heap` (for trivially simple cases)
For very simple cases with a single linear code path and no branching between acquiring and releasing the value, a direct `drop_with_heap` call is fine:
```rust
let iter = self.pop();
iter.drop_with_heap(&mut self.heap); // single path, no branching
```
Avoid manual `drop_with_heap` whenever there are multiple code paths (branching, `?`, `continue`, early returns) between acquiring and releasing the value — that is exactly where `defer_drop!` or `HeapGuard` prevent leaks by guaranteeing cleanup on every path.
## Dev Commands
DO NOT run `cargo build` or `cargo run`, it will fail because of issues with Python bindings.
Instead use the following `make` commands:
```bash
make install-py Install python dependencies
make install-js Install JS package dependencies
make install Install the package, dependencies, and pre-commit for local development
make dev-py Install the python package for development
make dev-js Build the JS package (debug)
make lint-js Lint JS code with oxlint
make test-js Build and test the JS package
make dev-py-release Install the python package for development with a release build
make dev-js-release Build the JS package (release)
make dev-py-pgo Install the python package for development with profile-guided optimization
make format-rs Format Rust code with fmt
make format-py Format Python code - WARNING be careful about this command as it may modify code and break tests silently!
make format-js Format JS code with prettier
make format Format Rust code, this does not format Python code as we have to be careful with that
make lint-rs Lint Rust code with clippy and import checks
make clippy-fix Fix Rust code with clippy
make lint-py Lint Python code with ruff
make lint Lint the code with ruff and clippy
make format-lint-rs Format and lint Rust code with fmt and clippy
make format-lint-py Format and lint Python code with ruff
make test-no-features Run rust tests without any features enabled
make test-ref-count-panic Run rust tests with ref-count-panic enabled
make test-ref-count-return Run rust tests with ref-count-return enabled
make test-cases Run tests cases only
make test-type-checking Run rust tests on monty_type_checking
make pytest Run Python tests with pytest
make test-py Build the python package (debug profile) and run tests
make test-docs Test docs examples only
make test Run rust tests
make testcov Run Rust tests with coverage, print table, and generate HTML report
make complete-tests Fill in incomplete test expectations using CPython
make update-typeshed Update vendored typeshed from upstream
make bench Run benchmarks
make dev-bench Run benchmarks to test with dev profile
make profile Profile the code with pprof and generate flamegraphs
make type-sizes Write type sizes for the crate to ./type-sizes.txt (requires nightly and top-type-sizes)
make main run linting and the most important tests
make help Show this help (usage: make help)
```
Use the /python-playground skill to check cpython and monty behavior.
## Releasing
See [RELEASING.md](RELEASING.md) for the release process.
## Exception
It's important that exceptions raised/returned by this library match those raised by Python.
Wherever you see an Exception with a repeated message, create a dedicated method to create that exception `src/exceptions.rs`.
When writing exception messages, always check `src/exceptions.rs` for existing methods to generate that message.
## Code style
Avoid local imports, unless there's a very good reason, all imports should be at the top of the file.
Avoid `fn my_func<T: MyTrait>(..., param: T)` style function definitions, STRONGLY prefer `fn my_func(param: impl MyTrait)` syntax since changes are more localized. This includes in trait definitions and implementations.
Also avoid using functions and structs via a path like `std::borrow::Cow::Owned(...)`, instead import `Cow` globally with `use std::borrow::Cow;`.
NEVER use `allow()` in rust lint markers, instead use `expect()` so any unnecessary markers are removed. E.g. use
```rs
#[expect(clippy::too_many_arguments)]
```
NOT!
```rs
#[allow(clippy::too_many_arguments)]
```
### Docstrings and comments.
IMPORTANT: every struct, enum and function should be a comprehensive but concise docstring to
explain what it does and why and any considerations or potential foot-guns of using that type.
The only exception is trait implementation methods where a docstring is not necessary if the method is self-explanatory.
It's important that docstrings cover the motivation and primary usage patterns of code, not just the simple "what it does".
Similarly, you should add comments to code, especially if the code is complex or esoteric.
Only add examples to docstrings of public functions and structs, examples should be <=8 lines, if the example is more, remove it.
If you add example code to docstrings, it must be run in tests. NEVER add examples that are ignored.
If you encounter a comment or docstring that's out of date - you MUST update it to be correct.
Similarly, if you encounter code that has no docstrings or comments, or they are minimal, you should add more detail.
NOTE: COMMENTS AND DOCSTRINGS ARE EXTREMELY IMPORTANT TO THE LONG TERM HEALTH OF THE PROJECT.
## Tests
Do **NOT** write tests within modules unless explicitly prompted to do so.
Tests should live in the relevant `tests/` directory.
Commands:
```bash
# Build the project
cargo build
# Run tests (this is the best way to run all tests as it enables the ref-count-panic feature)
make test-ref-count-panic
# Run crates/monty/test_cases tests only
make test-cases
# Run a specific test
cargo test -p monty --test datatest_runner --features ref-count-panic str__ops
# Run the interpreter on a Python file
cargo run -- <file.py>
```
See more test commands above.
### Experimentation and Playground
Read `Makefile` for other useful commands.
DO NOT run `cargo run --`, it will fail because of issues with Python bindings.
You can use the `./playground` directory (excluded from git, create with `mkdir -p playground`) to write files
when you want to experiment by running a file with cpython or monty, e.g.:
* `python3 playground/test.py` to run the file with cpython
* `cargo run -- playground/test.py` to run the file with monty
DO NOT use `/tmp` or pipe code to the interpreter as it requires extra permissions and can slow you down!
More details in the "python-playground" skill.
### Test File Structure
Most functionality should be tested via python files in the `crates/monty/test_cases` directory.
**DO NOT create many small test files.** This would be unmaintainable.
ALWAYS consolidate related tests into single files using multiple `assert` statements. Follow `crates/monty/test_cases/fstring__all.py` as the gold standard pattern:
```python
# === Section name ===
# brief comment if needed
assert condition, 'descriptive message'
assert another_condition, 'another descriptive message'
# === Next section ===
x = setup_value
assert x == expected, 'test description'
```
Each `assert` should have a descriptive message.
Do NOT Write tests like `assert 'thing' in msg` it's lazy and inexact unless explicitly told to do so, instead write tests like `assert msg == 'expected message'` to ensure clarity and accuracy and most importantly, to identify differences between Monty and CPython.
### When to Create Separate Test Files
Only create a separate test file when you MUST use one of these special expectation formats:
- `"""TRACEBACK:..."""` - Test expects an exception with full traceback (PREFERRED for error tests)
- `# Raise=Exception('message')` - Test expects an exception without traceback verification - NOT RECOMMENDED, use `TRACEBACK` instead
- `# ref-counts={...}` - Test checks reference counts (special mode)
- you're writing tests for a different behavior or section of the language
For everything else, **add asserts to an existing test file** or create ONE consolidated file for the feature.
### File Naming
Name files by feature, not by micro-variant:
- ✅ `str__ops.py` - all string operations (add, iadd, len, etc.)
- ✅ `list__methods.py` - all list method tests
- ❌ `str__add_basic.py`, `str__add_empty.py`, `str__add_multiple.py` - TOO GRANULAR
### Expectation Formats (use sparingly)
Only use these when `assert` won't work (on last line of file):
- `# Return=value` - Check `repr()` output (prefer assert instead)
- `# Return.str=value` - Check `str()` output (prefer assert instead)
- `# Return.type=typename` - Check `type()` output (prefer assert instead)
- `# Raise=Exception('message')` - Expect exception without traceback (REQUIRES separate file)
- `"""TRACEBACK:..."""` - Expect exception with full traceback (PREFERRED over `# Raise=`)
- `# ref-counts={...}` - Check reference counts (REQUIRES separate file)
- No expectation comment - Assert-based test (PREFERRED)
Do NOT use `# Return=` when you could use `assert` instead
### Traceback Tests (Preferred for Errors)
For tests that expect exceptions, **prefer traceback tests over `# Raise=`** because they verify:
- The full traceback with all stack frames
- Correct line numbers for each frame
- Function names in the traceback
- The caret markers (`~`) pointing to the error location
Traceback test format - add a triple-quoted string at the end of the file starting with `\nTRACEBACK:`:
```python
def foo():
raise ValueError('oops')
foo()
"""
TRACEBACK:
Traceback (most recent call last):
File "my_test.py", line 4, in <module>
foo()
~~~~~
File "my_test.py", line 2, in foo
raise ValueError('oops')
ValueError: oops
"""
```
Key points:
- The filename in the traceback should match the test file name (just the basename, not the full path)
- Use `~` for caret markers (the test runner normalizes CPython's `^` to `~`)
- The `<module>` frame name is used for top-level code
- Tests run against both Monty and CPython, so the traceback must match both
Only use `# Raise=` when you only care about the exception type/message and not the traceback.
### Python fixture markers
You may mark python files with:
* `# call-external` to support calling external functions
* `# run-async` to support running async code
NEVER MARK TESTS AS XFAIL UNDER ANY CIRCUMSTANCES!!! INSTEAD FIX THE BEHAVIOR SO THAT THE TEST PASSES.
Never mark tests as:
- `# xfail=cpython` - Test is required to fail on CPython
- `# xfail=monty` - Test is required to fail on Monty
NEVER MARK TESTS AS XFAIL UNDER ANY CIRCUMSTANCES!!! INSTEAD FIX THE BEHAVIOR SO THAT THE TEST PASSES.
All these markers must be at the start of comment lines to be recognized.
### Other Notes
- Prefer single quotes for strings in Python tests
- Do NOT add `# noqa` or `# pyright: ignore` comments to test code, instead add the failing code to `pyproject.toml`
- The ONLY exception is `await` expressions outside of async functions, where you should add `# pyright: ignore`
- Run `make lint-py` after adding tests
- Use `make complete-tests` to fill in blank expectations
- Tests run via `datatest-stable` harness in `tests/datatest_runner.rs`, use `make test-cases` to run them
## Python Package (`pydantic-monty`)
The Python package provides Python bindings for the Monty interpreter, located in `crates/monty-python/`.
### Structure
- `crates/monty-python/src/` - Rust source for PyO3 bindings
- `crates/monty-python/python/pydantic_monty/_monty.pyi` - Type stubs for the Python module
- `crates/monty-python/tests/` - Python tests using pytest
### Building and Testing
Dependencies needed for python testing are installed in `crates/monty-python/pyproject.toml`.
To install these dependencies, use `uv sync --all-packages --only-dev`.
```bash
# Build the Python package for development (required before running tests)
make dev-py
# Run Python tests
make test-py
# Or run pytest directly (after dev-py)
uv run pytest
# Run a specific test file
uv run pytest crates/monty-python/tests/test_basic.py
# Run a specific test
uv run pytest crates/monty-python/tests/test_basic.py::test_simple_expression
```
### Python Test Guidelines
Check and follow the style of other python tests.
Make sure you put tests in the correct file.
**DO NOT use python/pytest tests for `monty` core functionality!** When testing core functionality, add tests to `crates/monty/test_cases/` or `crates/monty/tests/`. Only use python/pytest tests for `pydantic_monty` functionality testing.
**NEVER use class-based tests.** All tests should be simple functions.
Use `@pytest.mark.parametrize` whenever testing multiple similar cases.
Use `snapshot` from `inline-snapshot` for all test asserts.
NEVER do the lazy `assert '...' in ...` instead always do `assert value == snapshot()`,
then run the test and inline-snapshot will fill in the missing value in the `snapshot()` call.
Use `pytest.raises` for expected exceptions, like this
```py
with pytest.raises(ValueError) as exc_info:
m.run(print_callback=callback)
assert exc_info.value.args[0] == snapshot('stopped at 3')
```
## Reference Counting
Heap-allocated values (`Value::Ref`) use manual reference counting. Key rules:
- **Cloning**: Use `clone_with_heap(heap)` which increments refcounts for `Ref` variants.
- **Dropping**: Call `drop_with_heap(heap)` when discarding an `Value` that may be a `Ref`.
Container types (`List`, `Tuple`, `Dict`) also have `clone_with_heap()` methods.
**Resource limits**: When resource limits (allocations, memory, time) are exceeded, execution terminates with a `ResourceError`. No guarantees are made about the state of the heap or reference counts after a resource limit is exceeded. The heap may contain orphaned objects with incorrect refcounts. This is acceptable because resource exhaustion is a terminal error - the execution context should be discarded.
## NOTES
ALWAYS consider code quality when adding new code, if functions are getting too complex or code is duplicated, move relevant logic to a new file.
Make sure functions are added in the most logical place, e.g. as methods on a struct where appropriate.
The code should follow the "newspaper" style where public and primary functions are at the top of the file, followed by private functions and utilities.
ALWAYS put utility, private functions and "sub functions" underneath the function they're used in.
It is important to the long term health of the project and maintainability of the codebase that code is well structured and organized, this is very important.
ALWAYS run `make format-rs` and `make lint-rs` after making changes to rust code and fix all suggestions to maintain code quality.
ALWAYS run `make lint-py` after making changes to python code and fix all suggestions to maintain code quality.
ALWAYS update this file when it is out of date.
NEVER add imports anywhere except at the top of the file, this applies to both python and rust.
NEVER write `unsafe` code, if you think you need to write unsafe code, explicitly ask the user or leave a `todo!()` with a suggestion and explanation.
## JavaScript Package (`monty-js`)
The JavaScript package provides Node.js bindings for the Monty interpreter via napi-rs, located in `crates/monty-js/`.
### Structure
- `crates/monty-js/src/lib.rs` - Rust source for napi-rs bindings
- `crates/monty-js/index.js` - Auto-generated JS loader that detects platform and loads the appropriate native binding
- `crates/monty-js/index.d.ts` - TypeScript type declarations (auto-generated)
- `crates/monty-js/__test__/` - Tests using ava
### Current API
The package exposes:
- `Monty` class - Parse and execute Python code with inputs, external functions, and resource limits
- `MontySnapshot` / `MontyComplete` - For iterative execution with `start()` / `resume()`
- `runMontyAsync()` - Helper for async external functions
- `MontySyntaxError` / `MontyRuntimeError` / `MontyTypingError` - Error classes
```ts
import { Monty, MontySnapshot, runMontyAsync } from '@pydantic/monty'
// Basic execution
const m = new Monty('x + 1', { inputs: ['x'] })
const result = m.run({ inputs: { x: 10 } }) // returns 11
// Iterative execution for external functions
const m2 = new Monty('fetch(url)', { inputs: ['url'], externalFunctions: ['fetch'] })
let progress = m2.start({ inputs: { url: 'https://...' } })
if (progress instanceof MontySnapshot) {
progress = progress.resume({ returnValue: 'response data' })
}
```
See `crates/monty-js/README.md` for full API documentation.
### Building and Testing
```bash
# Install dependencies
make install-js
# Build native binding (debug)
make build-js
# Build native binding (release)
make build-js-release
# Run tests
make test-js
# Format JavaScript code
make format-js
# Lint JavaScript code
make lint-js
```
Or run directly in `crates/monty-js`:
```bash
npm install
npm run build # release build
npm run build:debug # debug build
npm test
```
### JavaScript Test Guidelines
- Tests use [ava](https://github.com/avajs/ava) and live in `crates/monty-js/__test__/`
- Tests are written in TypeScript
- Follow the existing test style in the `__test__/` directory
================================================
FILE: Cargo.toml
================================================
[workspace]
resolver = "2"
members = [
"crates/monty",
"crates/monty-cli",
"crates/monty-python",
"crates/monty-js",
"crates/monty-type-checking",
"crates/monty-typeshed",
"crates/fuzz"
]
default-members = ["crates/monty-cli"]
[workspace.package]
edition = "2024"
version = "0.0.8"
rust-version = "1.90"
license = "MIT"
authors = ["Samuel Colvin <samuel@pydantic.dev>"]
description = "A sandboxed, snapshotable Python interpreter written in Rust."
categories = ["compilers", "emulators", "development-tools"]
keywords = ["python", "interpreter", "sandbox", "embedded"]
homepage = "https://github.com/pydantic/monty/"
repository = "https://github.com/pydantic/monty/"
documentation = "https://github.com/pydantic/monty/"
[profile.release]
lto = "fat"
codegen-units = 1
strip = true
[profile.profiling]
inherits = "release"
debug = true
strip = false
lto = false
[workspace.dependencies]
# ruff, ty and related crates
ruff_python_parser = { git = "https://github.com/astral-sh/ruff.git", package = "ruff_python_parser", rev = "6ded4bed1651e30b34dd04cdaa50c763036abb0d" }
ruff_python_ast = { git = "https://github.com/astral-sh/ruff.git", package = "ruff_python_ast", rev = "6ded4bed1651e30b34dd04cdaa50c763036abb0d" }
ruff_text_size = { git = "https://github.com/astral-sh/ruff.git", package = "ruff_text_size", rev = "6ded4bed1651e30b34dd04cdaa50c763036abb0d" }
ruff_db = { git = "https://github.com/astral-sh/ruff.git", package = "ruff_db", rev = "6ded4bed1651e30b34dd04cdaa50c763036abb0d", features = ["serde"] }
ty_python_semantic = { git = "https://github.com/astral-sh/ruff.git", package = "ty_python_semantic", rev = "6ded4bed1651e30b34dd04cdaa50c763036abb0d" }
ty_module_resolver = { git = "https://github.com/astral-sh/ruff.git", package = "ty_module_resolver", rev = "6ded4bed1651e30b34dd04cdaa50c763036abb0d" }
ty_vendored = { git = "https://github.com/astral-sh/ruff.git", package = "ty_vendored", rev = "6ded4bed1651e30b34dd04cdaa50c763036abb0d" }
# salsa version matches current main of ruff
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "53421c2fff87426fa0bb51cab06632b87646de13", default-features = false, features = [
"compact_str",
"macros",
"salsa_unstable",
"inventory",
] }
# bigint and related crates
num-bigint = { version = "0.4", features = ["serde"] }
num-traits = "0.2"
num-integer = "0.1"
# others
indexmap = { version = "2.9", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
postcard = { version = "1.1", features = ["alloc"] }
sha2 = "0.10"
pretty_assertions = "1.4"
[workspace.lints.rust]
# codspeed cfg is set by codspeed-criterion-compat when running in CodSpeed environment
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(codspeed)'] }
[workspace.lints.rustdoc]
invalid_codeblock_attributes = "allow"
[workspace.lints.clippy]
dbg_macro = "warn"
use_self = "warn"
allow_attributes = "warn"
undocumented_unsafe_blocks = "warn"
redundant_clone = "warn"
# in general we lint against the pedantic group, but we will whitelist
# certain lints which we don't want to enforce
pedantic = { level = "warn", priority = -1 }
cast_precision_loss = "allow"
doc_markdown = "allow"
match_same_arms = "allow"
missing_errors_doc = "allow"
similar_names = "allow"
too_many_lines = "allow"
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) Pydantic Services Inc. 2026 to present
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
.DEFAULT_GOAL := main
.PHONY: .cargo
.cargo: ## Check that cargo is installed
@cargo --version || echo 'Please install cargo: https://github.com/rust-lang/cargo'
.PHONY: .uv
.uv: ## Check that uv is installed
@uv --version || echo 'Please install uv: https://docs.astral.sh/uv/getting-started/installation/'
.PHONY: .pre-commit
.pre-commit: ## Check that pre-commit is installed
@pre-commit -V || echo 'Please install pre-commit: https://pre-commit.com/'
.PHONY: install-py
install-py: .uv ## Install python dependencies
# --only-dev to avoid building the python package, use make dev-py for that
uv sync --all-packages --only-dev
.PHONY: install-js
install-js: ## Install JS package dependencies
cd crates/monty-js && npm install
.PHONY: install
install: .cargo .pre-commit install-py install-js ## Install the package, dependencies, and pre-commit for local development
cargo check --workspace
pre-commit install --install-hooks
.PHONY: dev-py
dev-py: ## Install the python package for development
uv run maturin develop --uv -m crates/monty-python/Cargo.toml
.PHONY: dev-js
dev-js: ## Build the JS package (debug)
cd crates/monty-js && npm run build:debug
.PHONY: lint-js
lint-js: install-js ## Lint JS code with oxlint
cd crates/monty-js && npm run lint
.PHONY: test-js
test-js: dev-js ## Build and test the JS package
cd crates/monty-js && npm test
.PHONY: smoke-test-js
smoke-test-js: ## Run smoke test for JS package (builds, packs, and tests installation)
cd crates/monty-js && npm run smoke-test
.PHONY: dev-py-release
dev-py-release: ## Install the python package for development with a release build
uv run maturin develop --uv -m crates/monty-python/Cargo.toml --release
.PHONY: dev-js-release
dev-js-release: ## Build the JS package (release)
cd crates/monty-js && npm run build
.PHONY: dev-py-pgo
dev-py-pgo: ## Install the python package for development with profile-guided optimization
$(eval PROFDATA := $(shell mktemp -d))
RUSTFLAGS='-Cprofile-generate=$(PROFDATA)' uv run maturin develop --uv -m crates/monty-python/Cargo.toml --release
uv run --package pydantic-monty --only-dev pytest crates/monty-python/tests -k "not test_parallel_exec"
$(eval LLVM_PROFDATA := $(shell rustup run stable bash -c 'echo $$RUSTUP_HOME/toolchains/$$RUSTUP_TOOLCHAIN/lib/rustlib/$$(rustc -Vv | grep host | cut -d " " -f 2)/bin/llvm-profdata'))
$(LLVM_PROFDATA) merge -o $(PROFDATA)/merged.profdata $(PROFDATA)
RUSTFLAGS='-Cprofile-use=$(PROFDATA)/merged.profdata' $(uv-run-no-sync) maturin develop --uv -m crates/monty-python/Cargo.toml --release
@rm -rf $(PROFDATA)
.PHONY: format-rs
format-rs: ## Format Rust code with fmt
@cargo +nightly fmt --version
cargo +nightly fmt --all
.PHONY: format-py
format-py: ## Format Python code - WARNING be careful about this command as it may modify code and break tests silently!
uv run ruff format
uv run ruff check --fix --fix-only
.PHONY: format-js
format-js: install-js ## Format JS code with prettier
cd crates/monty-js && npm run format:prettier
.PHONY: format
format: format-rs format-py format-js ## Format Rust code, this does not format Python code as we have to be careful with that
.PHONY: lint-rs
lint-rs: ## Lint Rust code with clippy and import checks
@cargo clippy --version
cargo clippy --workspace --tests --bench main -- -D warnings
cargo clippy --workspace --tests --all-features -- -D warnings
uv run scripts/check_imports.py
.PHONY: clippy-fix
clippy-fix: ## Fix Rust code with clippy
cargo clippy --workspace --tests --bench main --all-features --fix --allow-dirty
.PHONY: lint-py
lint-py: dev-py ## Lint Python code with ruff
uv run ruff format --check
uv run ruff check
uv run basedpyright
# mypy-stubtest requires a build of the python package, hence dev-py
uv run -m mypy.stubtest pydantic_monty._monty --ignore-disjoint-bases
.PHONY: lint
lint: lint-rs lint-py ## Lint the code with ruff and clippy
.PHONY: format-lint-rs
format-lint-rs: format-rs lint-rs ## Format and lint Rust code with fmt and clippy
.PHONY: format-lint-py
format-lint-py: format-py lint-py ## Format and lint Python code with ruff
.PHONY: test-no-features
test-no-features: ## Run rust tests without any features enabled
cargo test -p monty
.PHONY: test-ref-count-panic
test-ref-count-panic: ## Run rust tests with ref-count-panic enabled
cargo test -p monty --features ref-count-panic
.PHONY: test-ref-count-return
test-ref-count-return: ## Run rust tests with ref-count-return enabled
cargo test -p monty --features ref-count-return
.PHONY: test-cases
test-cases: ## Run tests cases only
cargo test -p monty --test datatest_runner
.PHONY: test-type-checking
test-type-checking: ## Run rust tests on monty_type_checking
cargo test -p monty_type_checking -p monty_typeshed
.PHONY: pytest
pytest: ## Run Python tests with pytest
uv run --package pydantic-monty --only-dev pytest crates/monty-python/tests
.PHONY: test-py
test-py: dev-py pytest ## Build the python package (debug profile) and run tests
.PHONY: test-docs
test-docs: dev-py ## Test docs examples only
uv run --package pydantic-monty --only-dev pytest crates/monty-python/tests/test_readme_examples.py
cargo test --doc -p monty
.PHONY: test
test: test-ref-count-panic test-ref-count-return test-no-features test-type-checking test-py ## Run rust tests
.PHONY: testcov
testcov: ## Run Rust tests with coverage, print table, and generate HTML report
@cargo llvm-cov --version > /dev/null 2>&1 || echo 'Please run: `cargo install cargo-llvm-cov`'
cargo llvm-cov clean --workspace
echo "coverage for `make test-no-features`"
cargo llvm-cov --no-report -p monty
echo "coverage for `make test-ref-count-panic`"
cargo llvm-cov --no-report -p monty --features ref-count-panic
echo "coverage for `make test-ref-count-return`"
cargo llvm-cov --no-report -p monty --features ref-count-return
echo "coverage for `make test-type-checking`"
cargo llvm-cov --no-report -p monty_type_checking -p monty_typeshed
echo "Generating reports:"
cargo llvm-cov report --ignore-filename-regex '(tests/|test_cases/|/tests\.rs$$)'
cargo llvm-cov report --html --ignore-filename-regex '(tests/|test_cases/|/tests\.rs$$)'
@echo ""
@echo "HTML report: $${CARGO_TARGET_DIR:-target}/llvm-cov/html/index.html"
.PHONY: complete-tests
complete-tests: ## Fill in incomplete test expectations using CPython
uv run scripts/complete_tests.py
.PHONY: update-typeshed
update-typeshed: ## Update vendored typeshed from upstream
uv run crates/monty-typeshed/update.py
uv run ruff format
uv run ruff check --fix --fix-only --silent
.PHONY: bench
bench: ## Run benchmarks
cargo bench -p monty --bench main
.PHONY: dev-bench
dev-bench: ## Run benchmarks to test with dev profile
cargo bench --profile dev -p monty --bench main -- --test
.PHONY: profile
profile: ## Profile the code with pprof and generate flamegraphs
cargo bench -p monty --bench main --profile profiling -- --profile-time=10
uv run scripts/flamegraph_to_text.py
.PHONY: type-sizes
type-sizes: ## Write type sizes for the crate to ./type-sizes.txt (requires nightly and top-type-sizes)
RUSTFLAGS="-Zprint-type-sizes" cargo +nightly build -j1 2>&1 | top-type-sizes -f '^monty.*' > type-sizes.txt
@echo "Type sizes written to ./type-sizes.txt"
.PHONY: fuzz-string_input_panic
fuzz-string_input_panic: ## Run the `string_input_panic` fuzz target
cargo +nightly fuzz run --fuzz-dir crates/fuzz string_input_panic
.PHONY: fuzz-tokens_input_panic
fuzz-tokens_input_panic: ## Run the `tokens_input_panic` fuzz target (structured token input)
cargo +nightly fuzz run --fuzz-dir crates/fuzz tokens_input_panic
.PHONY: main
main: lint test-ref-count-panic test-py ## run linting and the most important tests
# (must stay last!)
.PHONY: help
help: ## Show this help (usage: make help)
@echo "Usage: make [recipe]"
@echo "Recipes:"
@awk '/^[a-zA-Z0-9_-]+:.*?##/ { \
helpMessage = match($$0, /## (.*)/); \
if (helpMessage) { \
recipe = $$1; \
sub(/:/, "", recipe); \
printf " \033[36mmake %-20s\033[0m %s\n", recipe, substr($$0, RSTART + 3, RLENGTH); \
} \
}' $(MAKEFILE_LIST)
================================================
FILE: README.md
================================================
<div align="center">
<h1>Monty</h1>
</div>
<div align="center">
<h3>A minimal, secure Python interpreter written in Rust for use by AI.</h3>
</div>
<div align="center">
<a href="https://github.com/pydantic/monty/actions/workflows/ci.yml?query=branch%3Amain"><img src="https://github.com/pydantic/monty/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://codspeed.io/pydantic/monty?utm_source=badge"><img src="https://img.shields.io/badge/CodSpeed-Performance%20Tracked-blue?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNOCAwTDAgOEw4IDE2TDE2IDhMOCAwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4=" alt="Codspeed"></a>
<a href="https://codecov.io/gh/pydantic/monty"><img src="https://codecov.io/gh/pydantic/monty/graph/badge.svg?token=HX4RDQX5OG" alt="Coverage"></a>
<a href="https://pypi.python.org/pypi/pydantic-monty"><img src="https://img.shields.io/pypi/v/pydantic-monty.svg" alt="PyPI"></a>
<a href="https://github.com/pydantic/monty"><img src="https://img.shields.io/pypi/pyversions/pydantic-monty.svg" alt="versions"></a>
<a href="https://github.com/pydantic/monty/blob/main/LICENSE"><img src="https://img.shields.io/github/license/pydantic/monty.svg?v=2" alt="license"></a>
<a href="https://logfire.pydantic.dev/docs/join-slack/"><img src="https://img.shields.io/badge/Slack-Join%20Slack-4A154B?logo=slack" alt="Join Slack" /></a>
</div>
---
**Experimental** - This project is still in development, and not ready for the prime time.
A minimal, secure Python interpreter written in Rust for use by AI.
Monty avoids the cost, latency, complexity and general faff of using a full container based sandbox for running LLM generated code.
Instead, it lets you safely run Python code written by an LLM embedded in your agent, with startup times measured in single digit microseconds not hundreds of milliseconds.
What Monty **can** do:
- Run a reasonable subset of Python code - enough for your agent to express what it wants to do
- Completely block access to the host environment: filesystem, env variables and network access are all implemented via external function calls the developer can control
- Call functions on the host - only functions you give it access to
- Run typechecking - monty supports full modern python type hints and comes with [ty](https://docs.astral.sh/ty/) included in a single binary to run typechecking
- Be snapshotted to bytes at external function calls, meaning you can store the interpreter state in a file or database, and resume later
- Startup extremely fast (<1μs to go from code to execution result), and has runtime performance that is similar to CPython (generally between 5x faster and 5x slower)
- Be called from Rust, Python, or Javascript - because Monty has no dependencies on cpython, you can use it anywhere you can run Rust
- Control resource usage - Monty can track memory usage, allocations, stack depth, and execution time and cancel execution if it exceeds preset limits
- Collect stdout and stderr and return it to the caller
- Run async or sync code on the host via async or sync code on the host
- Use a small subset of the standard library: `sys`, `os`, `typing`, `asyncio`, `re`, `datetime` (soon), `dataclasses` (soon), `json` (soon)
What Monty **cannot** do:
- Use the rest of the standard library
- Use third party libraries (like Pydantic), support for external python library is not a goal
- define classes (support should come soon)
- use match statements (again, support should come soon)
---
In short, Monty is extremely limited and designed for **one** use case:
**To run code written by agents.**
For motivation on why you might want to do this, see:
- [Codemode](https://blog.cloudflare.com/code-mode/) from Cloudflare
- [Programmatic Tool Calling](https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling) from Anthropic
- [Code Execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp) from Anthropic
- [Smol Agents](https://github.com/huggingface/smolagents) from Hugging Face
In very simple terms, the idea of all the above is that LLMs can work faster, cheaper and more reliably if they're asked to write Python (or Javascript) code, instead of relying on traditional tool calling. Monty makes that possible without the complexity of a sandbox or risk of running code directly on the host.
**Note:** Monty will (soon) be used to implement `codemode` in [Pydantic AI](https://github.com/pydantic/pydantic-ai)
## Usage
Monty can be called from Python, JavaScript/TypeScript or Rust.
### Python
To install:
```bash
uv add pydantic-monty
```
(Or `pip install pydantic-monty` for the boomers)
Usage:
```python
from typing import Any
import pydantic_monty
code = """
async def agent(prompt: str, messages: Messages):
while True:
print(f'messages so far: {messages}')
output = await call_llm(prompt, messages)
if isinstance(output, str):
return output
messages.extend(output)
await agent(prompt, [])
"""
type_definitions = """
from typing import Any
Messages = list[dict[str, Any]]
async def call_llm(prompt: str, messages: Messages) -> str | Messages:
raise NotImplementedError()
prompt: str = ''
"""
m = pydantic_monty.Monty(
code,
inputs=['prompt'],
script_name='agent.py',
type_check=True,
type_check_stubs=type_definitions,
)
Messages = list[dict[str, Any]]
async def call_llm(prompt: str, messages: Messages) -> str | Messages:
if len(messages) < 2:
return [{'role': 'system', 'content': 'example response'}]
else:
return f'example output, message count {len(messages)}'
async def main():
output = await pydantic_monty.run_monty_async(
m,
inputs={'prompt': 'testing'},
external_functions={'call_llm': call_llm},
)
print(output)
#> example output, message count 2
if __name__ == '__main__':
import asyncio
asyncio.run(main())
```
#### Iterative Execution with External Functions
Use `start()` and `resume()` to handle external function calls iteratively,
giving you control over each call:
```python
import pydantic_monty
code = """
data = fetch(url)
len(data)
"""
m = pydantic_monty.Monty(code, inputs=['url'])
# Start execution - pauses when fetch() is called
result = m.start(inputs={'url': 'https://example.com'})
print(type(result))
#> <class 'pydantic_monty.FunctionSnapshot'>
print(result.function_name) # fetch
#> fetch
print(result.args)
#> ('https://example.com',)
# Perform the actual fetch, then resume with the result
result = result.resume(return_value='hello world')
print(type(result))
#> <class 'pydantic_monty.MontyComplete'>
print(result.output)
#> 11
```
#### Serialization
Both `Monty` and snapshot types like `FunctionSnapshot` can be serialized to bytes and restored later.
This allows caching parsed code or suspending execution across process boundaries:
```python
import pydantic_monty
# Serialize parsed code to avoid re-parsing
m = pydantic_monty.Monty('x + 1', inputs=['x'])
data = m.dump()
# Later, restore and run
m2 = pydantic_monty.Monty.load(data)
print(m2.run(inputs={'x': 41}))
#> 42
# Serialize execution state mid-flight
m = pydantic_monty.Monty('fetch(url)', inputs=['url'])
progress = m.start(inputs={'url': 'https://example.com'})
state = progress.dump()
# Later, restore and resume (e.g., in a different process)
progress2 = pydantic_monty.load_snapshot(state)
result = progress2.resume(return_value='response data')
print(result.output)
#> response data
```
### Rust
```rust
use monty::{MontyRun, MontyObject, NoLimitTracker, PrintWriter};
let code = r#"
def fib(n):
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
fib(x)
"#;
let runner = MontyRun::new(code.to_owned(), "fib.py", vec!["x".to_owned()]).unwrap();
let result = runner.run(vec![MontyObject::Int(10)], NoLimitTracker, PrintWriter::Stdout).unwrap();
assert_eq!(result, MontyObject::Int(55));
```
#### Serialization
`MontyRun` and `RunProgress` can be serialized using the `dump()` and `load()` methods:
```rust
use monty::{MontyRun, MontyObject, NoLimitTracker, PrintWriter};
// Serialize parsed code
let runner = MontyRun::new("x + 1".to_owned(), "main.py", vec!["x".to_owned()]).unwrap();
let bytes = runner.dump().unwrap();
// Later, restore and run
let runner2 = MontyRun::load(&bytes).unwrap();
let result = runner2.run(vec![MontyObject::Int(41)], NoLimitTracker, PrintWriter::Stdout).unwrap();
assert_eq!(result, MontyObject::Int(42));
```
## PydanticAI Integration
Monty will power code-mode in
[Pydantic AI](https://github.com/pydantic/pydantic-ai). Instead of making
sequential tool calls, the LLM writes Python code that calls your tools
as functions and Monty executes it safely.
```python test="skip"
import asyncio
import json
import logfire
from httpx import AsyncClient
from pydantic_ai import Agent, RunContext
from pydantic_ai.toolsets.code_mode import CodeModeToolset
from pydantic_ai.toolsets.function import FunctionToolset
from typing_extensions import TypedDict
logfire.configure()
logfire.instrument_pydantic_ai()
class LatLng(TypedDict):
lat: float
lng: float
weather_toolset: FunctionToolset[AsyncClient] = FunctionToolset()
@weather_toolset.tool
async def get_lat_lng(
ctx: RunContext[AsyncClient], location_description: str
) -> LatLng:
"""Get the latitude and longitude of a location."""
# NOTE: the response here will be random, and is not related to the location description.
r = await ctx.deps.get(
'https://demo-endpoints.pydantic.workers.dev/latlng',
params={'location': location_description},
)
r.raise_for_status()
return json.loads(r.content)
@weather_toolset.tool
async def get_temp(ctx: RunContext[AsyncClient], lat: float, lng: float) -> float:
"""Get the temp at a location."""
# NOTE: the responses here will be random, and are not related to the lat and lng.
r = await ctx.deps.get(
'https://demo-endpoints.pydantic.workers.dev/number',
params={'min': 10, 'max': 30},
)
r.raise_for_status()
return float(r.text)
@weather_toolset.tool
async def get_weather_description(
ctx: RunContext[AsyncClient], lat: float, lng: float
) -> str:
"""Get the weather description at a location."""
# NOTE: the responses here will be random, and are not related to the lat and lng.
r = await ctx.deps.get(
'https://demo-endpoints.pydantic.workers.dev/weather',
params={'lat': lat, 'lng': lng},
)
r.raise_for_status()
return r.text
agent = Agent(
'gateway/anthropic:claude-sonnet-4-5',
# toolsets=[weather_toolset],
toolsets=[CodeModeToolset(weather_toolset)],
deps_type=AsyncClient,
)
async def main():
async with AsyncClient() as client:
await agent.run('Compare the weather of London, Paris, and Tokyo.', deps=client)
if __name__ == '__main__':
asyncio.run(main())
```
# Alternatives
There are generally two responses when you show people Monty:
1. Oh my god, this solves so many problems, I want it.
2. Why not X?
Where X is some alternative technology. Oddly often these responses are combined, suggesting people have not yet found an alternative that works for them, but are incredulous that there's really no good alternative to creating an entire Python implementation from scratch.
I'll try to run through the most obvious alternatives, and why there aren't right for what we wanted.
NOTE: all these technologies are impressive and have widespread uses, this commentary on their limitations for our use case should not be seen as a criticism. Most of these solutions were not conceived with the goal of providing an LLM sandbox, which is why they're not necessary great at it.
| Tech | Language completeness | Security | Start latency | FOSS | Setup complexity | File mounting | Snapshotting |
| ------------------ | --------------------- | ------------ | ------------- | ---------- | ---------------- | -------------- | ------------ |
| Monty | partial | strict | 0.06ms | free / OSS | easy | easy | easy |
| Docker | full | good | 195ms | free / OSS | intermediate | easy | intermediate |
| Pyodide | full | poor | 2800ms | free / OSS | intermediate | easy | hard |
| starlark-rust | very limited | good | 1.7ms | free / OSS | easy | not available? | impossible? |
| WASI / Wasmer | partial, almost full | strict | 66ms | free \* | intermediate | easy | intermediate |
| sandboxing service | full | strict | 1033ms | not free | intermediate | hard | intermediate |
| YOLO Python | full | non-existent | 0.1ms / 30ms | free / OSS | easy | easy / scary | hard |
See [./scripts/startup_performance.py](scripts/startup_performance.py) for the script used to calculate the startup performance numbers.
Details on each row below:
### Monty
- **Language completeness**: No classes (yet), limited stdlib, no third-party libraries
- **Security**: Explicitly controlled filesystem, network, and env access, strict limits on execution time and memory usage
- **Start latency**: Starts in microseconds
- **Setup complexity**: just `pip install pydantic-monty` or `npm install @pydantic/monty`, ~4.5MB download
- **File mounting**: Strictly controlled, see [#85](https://github.com/pydantic/monty/pull/85)
- **Snapshotting**: Monty's pause and resume functionality with `dump()` and `load()` makes it trivial to pause, resume and fork execution
### Docker
- **Language completeness**: Full CPython with any library
- **Security**: Process and filesystem isolation, network policies, but container escapes exist, memory limitation is possible
- **Start latency**: Container startup overhead (~195ms measured)
- **Setup complexity**: Requires Docker daemon, container images, orchestration, `python:3.14-alpine` is 50MB - docker can't be installed from PyPI
- **File mounting**: Volume mounts work well
- **Snapshotting**: Possible with durable execution solutions like Temporal, or snapshotting an image and saving it as a Docker image.
### Pyodide
- **Language completeness**: Full CPython compiled to WASM, almost all libraries available
- **Security**: Relies on browser/WASM sandbox - not designed for server-side isolation, python code can run arbitrary code in the JS runtime, only deno allows isolation, memory limits are hard/impossible to enforce with deno
- **Start latency**: WASM runtime loading is slow (~2800ms cold start)
- **Setup complexity**: Need to load WASM runtime, handle async initialization, pyodide NPM package is ~12MB, deno is ~50MB - Pyodide can't be called with just PyPI packages
- **File mounting**: Virtual filesystem via browser APIs
- **Snapshotting**: Possible with durable execution solutions like Temporal presumably, but hard
### starlark-rust
See [starlark-rust](https://github.com/facebook/starlark-rust).
- **Language completeness**: Configuration language, not Python - no classes, exceptions, async
- **Security**: Deterministic and hermetic by design
- **Start latency**: runs embedded in the process like Monty, hence impressive startup time
- **Setup complexity**: Usable in python via [starlark-pyo3](https://github.com/inducer/starlark-pyo3)
- **File mounting**: No file handling by design AFAIK?
- **Snapshotting**: Impossible AFAIK?
### WASI / Wasmer
Running Python in WebAssembly via [Wasmer](https://wasmer.io/).
- **Language completeness**: Full CPython, pure Python external packages work via mounting, external packages with C bindings don't work
- **Security**: In principle WebAssembly should provide strong sandboxing guarantees.
- **Start latency**: The [wasmer](https://pypi.org/project/wasmer/) python package hasn't been updated for 3 years and I couldn't find docs on calling Python in wasmer from Python, so I called it via subprocess. Start latency was 66ms.
- **Setup complexity**: wasmer download is 100mb, the "python/python" package is 50mb.
- **FOSS**: I marked this as "free \*" since the cost is zero but not everything seems to be open source. As of 2026-02-10 the [`python/python` wasmer package](https://wasmer.io/python/python) package has no readme, no license, no source link and no indication of how it's built, the recently uploaded versions show size as "0B" although the download is ~50MB - the build process for the Python binary is not clear and transparent. _(If I'm wrong here, please create an issue to correct correct me)_
- **File mounting**: Supported
- **Snapshotting**: Supported via journaling
### sandboxing service
Services like [Daytona](https://daytona.io), [E2B](https://e2b.dev), [Modal](https://modal.com).
There are similar challenges, more setup complexity but lower network latency for setting up your own sandbox setup with k8s.
- **Language completeness**: Full CPython with any library
- **Security**: Professionally managed container isolation
- **Start latency**: Network round-trip and container startup time. I got ~1s cold start time with Daytona EU from London, Daytona advertise sub 90ms latency, presumably that's for an existing container, not clear if it includes network latency
- **FOSS**: Pay per execution or compute time, some implementations are open source
- **Setup complexity**: API integration, auth tokens - fine for startups but generally a non-start for enterprises
- **File mounting**: Upload/download via API calls
- **Snapshotting**: Possible with durable execution solutions like Temporal, also the services offer some solutions for this, I think based con docker containers
### YOLO Python
Running Python directly via `exec()` (~0.1ms) or subprocess (~30ms).
- **Language completeness**: Full CPython with any library
- **Security**: None - full filesystem, network, env vars, system commands
- **Start latency**: Near-zero for `exec()`, ~30ms for subprocess
- **Setup complexity**: None
- **File mounting**: Direct filesystem access (that's the problem)
- **Snapshotting**: Possible with durable execution solutions like Temporal
================================================
FILE: RELEASING.md
================================================
# Release Process
## 1. Bump Version
Update version in both files:
```bash
# Edit Cargo.toml - update workspace.package.version
# Edit crates/monty-js/package.json - update version
# Update Cargo.lock
make lint-rs
```
Both `Cargo.toml` and `package.json` should have the same version (e.g., `0.0.2`).
## 2. Commit and Push
```bash
git add Cargo.toml Cargo.lock crates/monty-js/package.json
git commit -m "Bump version to X.Y.Z"
git push
```
## 3. Create Release via GitHub UI
1. Go to https://github.com/pydantic/monty/releases/new
2. Click "Choose a tag" and type the new tag name (e.g., `v0.0.2`)
3. Select "Create new tag on publish"
4. Set the release title (e.g., `v0.0.2`)
5. Add release notes
6. Click "Publish release"
## 4. CI Handles Publishing
Once the tag is pushed, CI will:
- Build wheels for all platforms
- Publish to PyPI (`pydantic-monty`)
- Publish to NPM (`@pydantic/monty`)
Monitor the workflow at https://github.com/pydantic/monty/actions
## Pre-release Tags
For pre-releases (alpha, beta, rc), use a tag like `v0.0.2-beta.1`:
- PyPI: Published normally
- NPM: Published with `--tag next` (not `latest`)
================================================
FILE: crates/fuzz/Cargo.toml
================================================
[package]
name = "monty-fuzz"
publish = false
version = { workspace = true }
edition = { workspace = true }
[package.metadata]
cargo-fuzz = true
[dependencies]
arbitrary = { version = "1", features = ["derive"] }
libfuzzer-sys = "0.4"
monty = { path = "../monty" }
[[bin]]
name = "string_input_panic"
path = "fuzz_targets/string_input_panic.rs"
test = false
doc = false
bench = false
[[bin]]
name = "tokens_input_panic"
path = "fuzz_targets/tokens_input_panic.rs"
test = false
doc = false
bench = false
[lints]
workspace = true
================================================
FILE: crates/fuzz/fuzz_targets/string_input_panic.rs
================================================
//! Fuzz target for testing that arbitrary Python code doesn't cause panics or crashes.
//!
//! This target feeds arbitrary byte sequences to the Monty interpreter and verifies that
//! neither parsing nor execution causes the interpreter to panic or crash. Errors (parse
//! errors, runtime errors, etc.) are expected and ignored - we only care about panics.
//!
//! Resource limits are enforced to prevent infinite loops and memory exhaustion.
#![no_main]
use std::time::Duration;
use libfuzzer_sys::fuzz_target;
use monty::{LimitedTracker, MontyRun, PrintWriter, ResourceLimits};
/// Resource limits for fuzzing - restrictive to prevent hangs and memory issues.
fn fuzz_limits() -> LimitedTracker {
LimitedTracker::new(
ResourceLimits::new()
.max_allocations(10_000)
.max_memory(1024 * 1024) // 1 MB
.max_duration(Duration::from_millis(100)),
)
}
fuzz_target!(|code: String| {
// Try to parse the code
let Ok(runner) = MontyRun::new(
code.to_owned(),
"fuzz.py",
vec![], // no inputs
) else {
return; // Parse errors are expected for random input
};
// Try to execute with resource limits - ignore all errors, we only care about panics/crashes
let _ = runner.run(vec![], fuzz_limits(), PrintWriter::Disabled);
});
================================================
FILE: crates/fuzz/fuzz_targets/tokens_input_panic.rs
================================================
//! Fuzz target using structured token input instead of random strings.
//!
//! This generates more syntactically plausible Python code by combining
//! tokens that represent common Python constructs. The fuzzer explores
//! combinations of these tokens to find edge cases.
#![no_main]
use std::{
fmt::{self, Display},
time::Duration,
};
use arbitrary::Arbitrary;
use libfuzzer_sys::fuzz_target;
use monty::{LimitedTracker, MontyRun, PrintWriter, ResourceLimits};
/// A token representing a piece of Python syntax.
#[derive(Debug, Clone, Arbitrary)]
enum Token {
// === Literals ===
String(StringLit),
Int(i64),
Float(FloatLit),
Bool(bool),
None,
// === Identifiers ===
Var(VarName),
Attr(AttrName),
// === Operators ===
BinOp(BinOp),
UnaryOp(UnaryOp),
CompareOp(CompareOp),
AugAssign(AugAssign),
// === Keywords ===
Keyword(Keyword),
// === Punctuation ===
LParen,
RParen,
LBracket,
RBracket,
LBrace,
RBrace,
Comma,
Colon,
Semicolon,
Dot,
Arrow,
Assign,
Walrus,
// === Whitespace/Structure ===
Space,
Newline,
Indent(IndentLevel),
Comment,
}
/// String literal variants.
#[derive(Debug, Clone, Arbitrary)]
enum StringLit {
Empty,
Short(ShortString),
FString(ShortString),
Raw(ShortString),
Bytes(ShortString),
}
/// Short string content (limited to avoid huge inputs).
#[derive(Debug, Clone, Arbitrary)]
enum ShortString {
Hello,
World,
Test,
Foo,
Bar,
Empty,
Space,
Newline,
Number,
Special,
}
/// Float literal (avoiding infinity/NaN issues).
#[derive(Debug, Clone, Arbitrary)]
enum FloatLit {
Zero,
One,
Half,
Pi,
Negative,
Small,
Large,
}
/// Common variable names.
#[derive(Debug, Clone, Arbitrary)]
enum VarName {
X,
Y,
Z,
A,
B,
C,
I,
J,
N,
Foo,
Bar,
Baz,
Spam,
Eggs,
Result,
Value,
Item,
Data,
Args,
Kwargs,
Self_,
Cls,
}
/// Common attribute names.
#[derive(Debug, Clone, Arbitrary)]
enum AttrName {
Append,
Pop,
Get,
Set,
Keys,
Values,
Items,
Join,
Split,
Strip,
Lower,
Upper,
Format,
Replace,
Find,
Count,
Sort,
Reverse,
Copy,
Clear,
Update,
Add,
Remove,
}
/// Binary operators.
#[derive(Debug, Clone, Arbitrary)]
enum BinOp {
Add,
Sub,
Mul,
Div,
FloorDiv,
Mod,
Pow,
MatMul,
BitAnd,
BitOr,
BitXor,
LShift,
RShift,
And,
Or,
}
/// Unary operators.
#[derive(Debug, Clone, Arbitrary)]
enum UnaryOp {
Neg,
Pos,
Not,
Invert,
}
/// Comparison operators.
#[derive(Debug, Clone, Arbitrary)]
enum CompareOp {
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
Is,
IsNot,
In,
NotIn,
}
/// Augmented assignment operators.
#[derive(Debug, Clone, Arbitrary)]
enum AugAssign {
AddEq,
SubEq,
MulEq,
DivEq,
FloorDivEq,
ModEq,
PowEq,
AndEq,
OrEq,
XorEq,
LShiftEq,
RShiftEq,
}
/// Python keywords.
#[derive(Debug, Clone, Arbitrary)]
enum Keyword {
If,
Elif,
Else,
For,
While,
Break,
Continue,
Pass,
Return,
Def,
Lambda,
Async,
Await,
Try,
Except,
Finally,
Raise,
Assert,
Import,
From,
As,
Global,
Nonlocal,
}
/// Indentation levels (0-4 levels deep).
#[derive(Debug, Clone, Arbitrary)]
enum IndentLevel {
L0,
L1,
L2,
L3,
L4,
}
impl Display for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::String(s) => write!(f, "{s}"),
Self::Int(n) => write!(f, "{n}"),
Self::Float(fl) => write!(f, "{fl}"),
Self::Bool(true) => write!(f, "True"),
Self::Bool(false) => write!(f, "False"),
Self::None => write!(f, "None"),
Self::Var(v) => write!(f, "{v}"),
Self::Attr(a) => write!(f, "{a}"),
Self::BinOp(op) => write!(f, "{op}"),
Self::UnaryOp(op) => write!(f, "{op}"),
Self::CompareOp(op) => write!(f, "{op}"),
Self::AugAssign(op) => write!(f, "{op}"),
Self::Keyword(kw) => write!(f, "{kw}"),
Self::LParen => write!(f, "("),
Self::RParen => write!(f, ")"),
Self::LBracket => write!(f, "["),
Self::RBracket => write!(f, "]"),
Self::LBrace => write!(f, "{{"),
Self::RBrace => write!(f, "}}"),
Self::Comma => write!(f, ","),
Self::Colon => write!(f, ":"),
Self::Semicolon => write!(f, ";"),
Self::Dot => write!(f, "."),
Self::Arrow => write!(f, "->"),
Self::Assign => write!(f, "="),
Self::Walrus => write!(f, ":="),
Self::Space => write!(f, " "),
Self::Newline => writeln!(f),
Self::Indent(level) => write!(f, "{level}"),
Self::Comment => write!(f, "# comment"),
}
}
}
impl Display for StringLit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Empty => write!(f, "''"),
Self::Short(s) => write!(f, "'{s}'"),
Self::FString(s) => write!(f, "f'{s}'"),
Self::Raw(s) => write!(f, "r'{s}'"),
Self::Bytes(s) => write!(f, "b'{s}'"),
}
}
}
impl Display for ShortString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Hello => write!(f, "hello"),
Self::World => write!(f, "world"),
Self::Test => write!(f, "test"),
Self::Foo => write!(f, "foo"),
Self::Bar => write!(f, "bar"),
Self::Empty => write!(f, ""),
Self::Space => write!(f, " "),
Self::Newline => write!(f, "\\n"),
Self::Number => write!(f, "123"),
Self::Special => write!(f, "{{}}"),
}
}
}
impl Display for FloatLit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Zero => write!(f, "0.0"),
Self::One => write!(f, "1.0"),
Self::Half => write!(f, "0.5"),
Self::Pi => write!(f, "3.14159"),
Self::Negative => write!(f, "-1.5"),
Self::Small => write!(f, "0.001"),
Self::Large => write!(f, "1e10"),
}
}
}
impl Display for VarName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::X => write!(f, "x"),
Self::Y => write!(f, "y"),
Self::Z => write!(f, "z"),
Self::A => write!(f, "a"),
Self::B => write!(f, "b"),
Self::C => write!(f, "c"),
Self::I => write!(f, "i"),
Self::J => write!(f, "j"),
Self::N => write!(f, "n"),
Self::Foo => write!(f, "foo"),
Self::Bar => write!(f, "bar"),
Self::Baz => write!(f, "baz"),
Self::Spam => write!(f, "spam"),
Self::Eggs => write!(f, "eggs"),
Self::Result => write!(f, "result"),
Self::Value => write!(f, "value"),
Self::Item => write!(f, "item"),
Self::Data => write!(f, "data"),
Self::Args => write!(f, "args"),
Self::Kwargs => write!(f, "kwargs"),
Self::Self_ => write!(f, "self"),
Self::Cls => write!(f, "cls"),
}
}
}
impl Display for AttrName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Append => write!(f, "append"),
Self::Pop => write!(f, "pop"),
Self::Get => write!(f, "get"),
Self::Set => write!(f, "set"),
Self::Keys => write!(f, "keys"),
Self::Values => write!(f, "values"),
Self::Items => write!(f, "items"),
Self::Join => write!(f, "join"),
Self::Split => write!(f, "split"),
Self::Strip => write!(f, "strip"),
Self::Lower => write!(f, "lower"),
Self::Upper => write!(f, "upper"),
Self::Format => write!(f, "format"),
Self::Replace => write!(f, "replace"),
Self::Find => write!(f, "find"),
Self::Count => write!(f, "count"),
Self::Sort => write!(f, "sort"),
Self::Reverse => write!(f, "reverse"),
Self::Copy => write!(f, "copy"),
Self::Clear => write!(f, "clear"),
Self::Update => write!(f, "update"),
Self::Add => write!(f, "add"),
Self::Remove => write!(f, "remove"),
}
}
}
impl Display for BinOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Add => write!(f, " + "),
Self::Sub => write!(f, " - "),
Self::Mul => write!(f, " * "),
Self::Div => write!(f, " / "),
Self::FloorDiv => write!(f, " // "),
Self::Mod => write!(f, " % "),
Self::Pow => write!(f, " ** "),
Self::MatMul => write!(f, " @ "),
Self::BitAnd => write!(f, " & "),
Self::BitOr => write!(f, " | "),
Self::BitXor => write!(f, " ^ "),
Self::LShift => write!(f, " << "),
Self::RShift => write!(f, " >> "),
Self::And => write!(f, " and "),
Self::Or => write!(f, " or "),
}
}
}
impl Display for UnaryOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Neg => write!(f, "-"),
Self::Pos => write!(f, "+"),
Self::Not => write!(f, "not "),
Self::Invert => write!(f, "~"),
}
}
}
impl Display for CompareOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Eq => write!(f, " == "),
Self::Ne => write!(f, " != "),
Self::Lt => write!(f, " < "),
Self::Le => write!(f, " <= "),
Self::Gt => write!(f, " > "),
Self::Ge => write!(f, " >= "),
Self::Is => write!(f, " is "),
Self::IsNot => write!(f, " is not "),
Self::In => write!(f, " in "),
Self::NotIn => write!(f, " not in "),
}
}
}
impl Display for AugAssign {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AddEq => write!(f, " += "),
Self::SubEq => write!(f, " -= "),
Self::MulEq => write!(f, " *= "),
Self::DivEq => write!(f, " /= "),
Self::FloorDivEq => write!(f, " //= "),
Self::ModEq => write!(f, " %= "),
Self::PowEq => write!(f, " **= "),
Self::AndEq => write!(f, " &= "),
Self::OrEq => write!(f, " |= "),
Self::XorEq => write!(f, " ^= "),
Self::LShiftEq => write!(f, " <<= "),
Self::RShiftEq => write!(f, " >>= "),
}
}
}
impl Display for Keyword {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::If => write!(f, "if "),
Self::Elif => write!(f, "elif "),
Self::Else => write!(f, "else"),
Self::For => write!(f, "for "),
Self::While => write!(f, "while "),
Self::Break => write!(f, "break"),
Self::Continue => write!(f, "continue"),
Self::Pass => write!(f, "pass"),
Self::Return => write!(f, "return "),
Self::Def => write!(f, "def "),
Self::Lambda => write!(f, "lambda "),
Self::Async => write!(f, "async "),
Self::Await => write!(f, "await "),
Self::Try => write!(f, "try"),
Self::Except => write!(f, "except "),
Self::Finally => write!(f, "finally"),
Self::Raise => write!(f, "raise "),
Self::Assert => write!(f, "assert "),
Self::Import => write!(f, "import "),
Self::From => write!(f, "from "),
Self::As => write!(f, " as "),
Self::Global => write!(f, "global "),
Self::Nonlocal => write!(f, "nonlocal "),
}
}
}
impl Display for IndentLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let spaces = match self {
Self::L0 => 0,
Self::L1 => 4,
Self::L2 => 8,
Self::L3 => 12,
Self::L4 => 16,
};
for _ in 0..spaces {
write!(f, " ")?;
}
Ok(())
}
}
/// Wrapper for `Vec<Token>` with custom Debug that shows both tokens and generated code.
struct Tokens(Vec<Token>);
impl<'a> Arbitrary<'a> for Tokens {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Vec::<Token>::arbitrary(u).map(Tokens)
}
}
impl fmt::Debug for Tokens {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Tokens")
.field("tokens", &self.0)
.field("code", &self.to_code())
.finish()
}
}
impl Tokens {
/// Convert the tokens to Python source code.
fn to_code(&self) -> String {
self.0.iter().map(|t| t.to_string()).collect()
}
}
/// Resource limits for fuzzing.
fn fuzz_limits() -> LimitedTracker {
LimitedTracker::new(
ResourceLimits::new()
.max_allocations(10_000)
.max_memory(1024 * 1024) // 1 MB
.max_duration(Duration::from_millis(100)),
)
}
fuzz_target!(|tokens: Tokens| {
let code = tokens.to_code();
// Try to parse the code
let Ok(runner) = MontyRun::new(code, "fuzz.py", vec![]) else {
return; // Parse errors are expected
};
// Try to execute with resource limits
let _ = runner.run(vec![], fuzz_limits(), PrintWriter::Disabled);
});
================================================
FILE: crates/monty/Cargo.toml
================================================
[package]
name = "monty"
readme = "../../README.md"
version = { workspace = true }
license = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
authors = { workspace = true }
description = { workspace = true }
keywords = { workspace = true }
categories = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[lib]
name = "monty"
path = "src/lib.rs"
[dependencies]
ruff_python_parser = { workspace = true }
ruff_python_ast = { workspace = true }
ruff_text_size = { workspace = true }
ahash = { version = "0.8.0", features = ["serde"] }
indexmap = { workspace = true }
serde = { workspace = true }
postcard = { workspace = true }
strum = { version = "0.27", features = ["derive"] }
hashbrown = "0.16"
num-bigint = { workspace = true }
num-traits = { workspace = true }
num-integer = { workspace = true }
smallvec = { version = "1.13", features = ["serde"] }
fancy-regex = "0.17.0"
libm = "0.2"
itertools = "0.14.0"
[features]
# ref-count-return changes behavior to return information on reference counts to check they're correct
# should be used for testing only
ref-count-return = []
# ref-count-panic enables a Drop implementation on Value which catches heap allocated values that are dropped
# without being dereferenced.
# should be used for testing only
ref-count-panic = []
[dev-dependencies]
pyo3 = { version = "0.28", features = ["auto-initialize"] }
# Use codspeed-criterion-compat for CI benchmarks, real criterion for local flamegraphs
codspeed-criterion-compat = "4.2.1"
criterion = "0.5"
datatest-stable = "0.2"
serde_json = "1.0"
pprof = { version = "0.15", features = ["flamegraph", "criterion"] }
similar = "2.7.0"
[build-dependencies]
pyo3-build-config = { version = "0.28", features = ["resolve-config"] }
[[bench]]
name = "main"
harness = false
[[test]]
name = "datatest_runner"
harness = false
[lints]
workspace = true
================================================
FILE: crates/monty/benches/main.rs
================================================
// Use codspeed-criterion-compat when running on CodSpeed (CI), real criterion otherwise (for flamegraphs)
#[cfg(not(codspeed))]
use std::ffi::CString;
#[cfg(codspeed)]
use codspeed_criterion_compat::{Bencher, Criterion, black_box, criterion_group, criterion_main};
#[cfg(not(codspeed))]
use criterion::{Bencher, Criterion, black_box, criterion_group, criterion_main};
use monty::MontyRun;
#[cfg(not(codspeed))]
use pprof::criterion::{Output, PProfProfiler};
// CPython benchmarks are only run locally, not on CodSpeed CI (requires Python + pyo3 setup)
#[cfg(not(codspeed))]
use pyo3::prelude::*;
/// Runs a benchmark using the Monty interpreter.
/// Parses once, then benchmarks repeated execution.
fn run_monty(bench: &mut Bencher, code: &str, expected: i64) {
let ex = MontyRun::new(code.to_owned(), "test.py", vec![]).unwrap();
let r = ex.run_no_limits(vec![]).unwrap();
let int_value: i64 = r.as_ref().try_into().unwrap();
assert_eq!(int_value, expected);
bench.iter(|| {
let r = ex.run_no_limits(vec![]).unwrap();
let int_value: i64 = r.as_ref().try_into().unwrap();
black_box(int_value);
});
}
/// Runs a benchmark using CPython.
/// Wraps code in main(), parses once, then benchmarks repeated execution.
#[cfg(not(codspeed))]
fn run_cpython(bench: &mut Bencher, code: &str, expected: i64) {
Python::attach(|py| {
let wrapped = wrap_for_cpython(code);
let code_cstr = CString::new(wrapped).expect("Invalid C string in code");
let fun: Py<PyAny> = PyModule::from_code(py, &code_cstr, c"test.py", c"main")
.unwrap()
.getattr("main")
.unwrap()
.into();
let r_py = fun.call0(py).unwrap();
let r: i64 = r_py.extract(py).unwrap();
assert_eq!(r, expected);
bench.iter(|| {
let r_py = fun.call0(py).unwrap();
let r: i64 = r_py.extract(py).unwrap();
black_box(r);
});
});
}
/// Wraps code in a main() function for CPython execution.
/// Indents each line and converts the last expression to a return statement.
#[cfg(not(codspeed))]
fn wrap_for_cpython(code: &str) -> String {
let mut lines: Vec<String> = Vec::new();
let mut last_expr = String::new();
for line in code.lines() {
// Skip test metadata comments
if line.starts_with("# Return=") || line.starts_with("# Raise=") || line.starts_with("# skip=") {
continue;
}
// Track the last non-empty, non-comment line as potential return expression
let trimmed = line.trim();
if !trimmed.is_empty() && !trimmed.starts_with('#') {
last_expr = line.to_string();
}
lines.push(format!(" {line}"));
}
// Replace last expression with return statement
if let Some(last) = lines.iter().rposition(|l| l.trim() == last_expr.trim()) {
lines[last] = format!(" return {}", last_expr.trim());
}
format!("def main():\n{}", lines.join("\n"))
}
const ADD_TWO: &str = "1 + 2";
const LIST_APPEND: &str = "
a = []
a.append(42)
a[0]
";
const LOOP_MOD_13: &str = "
v = ''
for i in range(1_000):
if i % 13 == 0:
v += 'x'
len(v)
";
/// Comprehensive benchmark exercising most supported Python features.
/// Code is shared with test_cases/bench__kitchen_sink.py
const KITCHEN_SINK: &str = include_str!("../test_cases/bench__kitchen_sink.py");
const FUNC_CALL_KWARGS: &str = "
def add(a, b=2):
return a + b
add(a=1)
";
const LIST_APPEND_STR: &str = "
a = []
for i in range(100_000):
a.append(str(i))
len(a)
";
const LIST_APPEND_INT: &str = "
a = []
for i in range(100_000):
a.append(i)
sum(a)
";
const FIB_25: &str = "
def fib(n):
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
fib(25)
";
/// List comprehension benchmark - creates 1000 elements.
const LIST_COMP: &str = "len([x * 2 for x in range(1000)])";
/// Dict comprehension benchmark - creates 500 unique keys (i // 2 deduplicates pairs).
const DICT_COMP: &str = "len({i // 2: i * 2 for i in range(1000)})";
/// Empty tuple creation benchmark - creates 100,000 empty tuples in a list.
const EMPTY_TUPLES: &str = "len([() for _ in range(100_000)])";
/// 2-tuple creation benchmark - creates 100,000 2-tuples in a list.
const PAIR_TUPLES: &str = "len([(i, i + 1) for i in range(100_000)])";
/// Benchmarks end-to-end execution (parsing + running) using Monty.
/// This is different from other benchmarks as it includes parsing in the loop.
fn end_to_end_monty(bench: &mut Bencher) {
bench.iter(|| {
let ex = MontyRun::new(black_box("1 + 2").to_owned(), "test.py", vec![]).unwrap();
let r = ex.run_no_limits(vec![]).unwrap();
let int_value: i64 = r.as_ref().try_into().unwrap();
black_box(int_value);
});
}
/// Benchmarks end-to-end execution (parsing + running) using CPython.
/// This is different from other benchmarks as it includes parsing in the loop.
#[cfg(not(codspeed))]
fn end_to_end_cpython(bench: &mut Bencher) {
Python::attach(|py| {
bench.iter(|| {
let fun: Py<PyAny> =
PyModule::from_code(py, black_box(c"def main():\n return 1 + 2"), c"test.py", c"main")
.unwrap()
.getattr("main")
.unwrap()
.into();
let r_py = fun.call0(py).unwrap();
let r: i64 = r_py.extract(py).unwrap();
black_box(r);
});
});
}
/// Configures all benchmarks in a single group.
fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("add_two__monty", |b| run_monty(b, ADD_TWO, 3));
#[cfg(not(codspeed))]
c.bench_function("add_two__cpython", |b| run_cpython(b, ADD_TWO, 3));
c.bench_function("list_append__monty", |b| run_monty(b, LIST_APPEND, 42));
#[cfg(not(codspeed))]
c.bench_function("list_append__cpython", |b| run_cpython(b, LIST_APPEND, 42));
c.bench_function("loop_mod_13__monty", |b| run_monty(b, LOOP_MOD_13, 77));
#[cfg(not(codspeed))]
c.bench_function("loop_mod_13__cpython", |b| run_cpython(b, LOOP_MOD_13, 77));
c.bench_function("end_to_end__monty", end_to_end_monty);
#[cfg(not(codspeed))]
c.bench_function("end_to_end__cpython", end_to_end_cpython);
c.bench_function("kitchen_sink__monty", |b| run_monty(b, KITCHEN_SINK, 373));
#[cfg(not(codspeed))]
c.bench_function("kitchen_sink__cpython", |b| run_cpython(b, KITCHEN_SINK, 373));
c.bench_function("func_call_kwargs__monty", |b| run_monty(b, FUNC_CALL_KWARGS, 3));
#[cfg(not(codspeed))]
c.bench_function("func_call_kwargs__cpython", |b| run_cpython(b, FUNC_CALL_KWARGS, 3));
c.bench_function("list_append_str__monty", |b| run_monty(b, LIST_APPEND_STR, 100_000));
#[cfg(not(codspeed))]
c.bench_function("list_append_str__cpython", |b| run_cpython(b, LIST_APPEND_STR, 100_000));
c.bench_function("list_append_int__monty", |b| {
run_monty(b, LIST_APPEND_INT, 4_999_950_000);
});
#[cfg(not(codspeed))]
c.bench_function("list_append_int__cpython", |b| {
run_cpython(b, LIST_APPEND_INT, 4_999_950_000);
});
c.bench_function("fib__monty", |b| run_monty(b, FIB_25, 75_025));
#[cfg(not(codspeed))]
c.bench_function("fib__cpython", |b| run_cpython(b, FIB_25, 75_025));
c.bench_function("list_comp__monty", |b| run_monty(b, LIST_COMP, 1000));
#[cfg(not(codspeed))]
c.bench_function("list_comp__cpython", |b| run_cpython(b, LIST_COMP, 1000));
c.bench_function("dict_comp__monty", |b| run_monty(b, DICT_COMP, 500));
#[cfg(not(codspeed))]
c.bench_function("dict_comp__cpython", |b| run_cpython(b, DICT_COMP, 500));
c.bench_function("empty_tuples__monty", |b| run_monty(b, EMPTY_TUPLES, 100_000));
#[cfg(not(codspeed))]
c.bench_function("empty_tuples__cpython", |b| run_cpython(b, EMPTY_TUPLES, 100_000));
c.bench_function("pair_tuples__monty", |b| run_monty(b, PAIR_TUPLES, 100_000));
#[cfg(not(codspeed))]
c.bench_function("pair_tuples__cpython", |b| run_cpython(b, PAIR_TUPLES, 100_000));
}
// Use pprof flamegraph profiler when running locally (not on CodSpeed)
#[cfg(not(codspeed))]
criterion_group!(
name = benches;
config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None)));
targets = criterion_benchmark
);
// Use default config when running on CodSpeed (pprof's Profiler trait is incompatible)
#[cfg(codspeed)]
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
================================================
FILE: crates/monty/build.rs
================================================
fn main() {
// This ensures that tests can find the libpython shared library at runtime, even if it's not on
// the system library path. This makes running tests much easier on e.g. Linux with a uv venv.
//
// This is technically a bit wasteful because the main `lib` doesn't need this, just tests, but it
// won't affect downstream executables other than requiring them to have a valid Python in their system.
//
// If that becomes a big problem, we can rethink.
pyo3_build_config::add_libpython_rpath_link_args();
}
================================================
FILE: crates/monty/src/args.rs
================================================
use std::vec::IntoIter;
use crate::{
MontyObject, ResourceTracker,
bytecode::VM,
defer_drop, defer_drop_mut,
exception_private::{ExcType, RunError, RunResult, SimpleException},
expressions::{ExprLoc, Identifier},
heap::{ContainsHeap, DropWithHeap, Heap, HeapGuard},
intern::{Interns, StringId},
parse::ParseError,
types::{Dict, dict::DictIntoIter},
value::Value,
};
/// Type for method call arguments.
///
/// Uses specific variants for common cases (0-2 arguments).
/// Most Python method calls have at most 2 arguments, so this optimization
/// eliminates the Vec heap allocation overhead for the vast majority of calls.
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub(crate) enum ArgValues {
Empty,
One(Value),
Two(Value, Value),
Kwargs(KwargsValues),
ArgsKargs { args: Vec<Value>, kwargs: KwargsValues },
}
impl ArgValues {
/// Checks that zero arguments were passed.
///
/// On error, properly drops all contained values to maintain reference counts.
pub fn check_zero_args(self, name: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<()> {
match self {
Self::Empty => Ok(()),
other => {
let count = other.count();
other.drop_with_heap(heap);
Err(ExcType::type_error_no_args(name, count))
}
}
}
/// Checks that exactly one positional argument was passed, returning it.
///
/// On error, properly drops all contained values to maintain reference counts.
pub fn get_one_arg(self, name: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Value> {
match self {
Self::One(a) => Ok(a),
other => {
let count = other.count();
other.drop_with_heap(heap);
Err(ExcType::type_error_arg_count(name, 1, count))
}
}
}
/// Checks that exactly two positional arguments were passed, returning them as a tuple.
///
/// On error, properly drops all contained values to maintain reference counts.
pub fn get_two_args(self, name: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<(Value, Value)> {
match self {
Self::Two(a1, a2) => Ok((a1, a2)),
other => {
let count = other.count();
other.drop_with_heap(heap);
Err(ExcType::type_error_arg_count(name, 2, count))
}
}
}
/// Checks that one or two arguments were passed, returning them as a tuple.
///
/// On error, properly drops all contained values to maintain reference counts.
pub fn get_one_two_args(
self,
name: &str,
heap: &mut Heap<impl ResourceTracker>,
) -> RunResult<(Value, Option<Value>)> {
match self {
Self::One(a) => Ok((a, None)),
Self::Two(a1, a2) => Ok((a1, Some(a2))),
other => {
let count = other.count();
other.drop_with_heap(heap);
if count == 0 {
Err(ExcType::type_error_at_least(name, 1, count))
} else {
Err(ExcType::type_error_at_most(name, 2, count))
}
}
}
}
/// Checks that zero or one argument was passed, returning the optional value.
///
/// On error, properly drops all contained values to maintain reference counts.
pub fn get_zero_one_arg(self, name: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<Option<Value>> {
match self {
Self::Empty => Ok(None),
Self::One(a) => Ok(Some(a)),
other => {
let count = other.count();
other.drop_with_heap(heap);
Err(ExcType::type_error_at_most(name, 1, count))
}
}
}
/// Checks that zero, one, or two arguments were passed.
///
/// Returns (None, None) for 0 args, (Some(a), None) for 1 arg, (Some(a), Some(b)) for 2 args.
/// On error, properly drops all contained values to maintain reference counts.
pub fn get_zero_one_two_args(
self,
name: &str,
heap: &mut Heap<impl ResourceTracker>,
) -> RunResult<(Option<Value>, Option<Value>)> {
match self {
Self::Empty => Ok((None, None)),
Self::One(a) => Ok((Some(a), None)),
Self::Two(a, b) => Ok((Some(a), Some(b))),
other => {
let count = other.count();
other.drop_with_heap(heap);
Err(ExcType::type_error_at_most(name, 2, count))
}
}
}
/// Extracts a keyword-only pair by name.
///
/// Validates that no positional arguments are provided and only the specified
/// keyword arguments are present. Returns `(None, None)` when neither keyword
/// is provided.
///
/// # Arguments
/// * `method_name` - Method name for error messages (e.g., "list.sort")
/// * `kwarg1` - Name of the first keyword argument
/// * `kwarg2` - Name of the second keyword argument
///
/// # Errors
/// Returns an error if:
/// - Any positional arguments are provided
/// - A keyword argument other than `kwarg1` or `kwarg2` is provided
/// - A keyword is not a string
pub fn extract_keyword_only_pair(
self,
method_name: &str,
kwarg1: &str,
kwarg2: &str,
heap: &mut Heap<impl ResourceTracker>,
interns: &Interns,
) -> RunResult<(Option<Value>, Option<Value>)> {
let (pos, kwargs) = self.into_parts();
defer_drop!(pos, heap);
// Check no positional arguments
if pos.len() > 0 {
kwargs.drop_with_heap(heap);
return Err(ExcType::type_error_no_args(method_name, 1));
}
kwargs.parse_named_kwargs_pair(method_name, kwarg1, kwarg2, heap, interns, |method_name, key_str| {
ExcType::type_error(format!(
"'{key_str}' is an invalid keyword argument for {method_name}()"
))
})
}
/// Prepends a value as the first positional argument.
///
/// Used to insert `self` when dispatching dataclass method calls to the host.
/// The dataclass instance becomes the first arg so the host can reconstruct
/// the original object and call the method on it.
pub fn prepend(self, value: Value) -> Self {
match self {
Self::Empty => Self::One(value),
Self::One(a) => Self::Two(value, a),
Self::Two(a, b) => Self::ArgsKargs {
args: vec![value, a, b],
kwargs: KwargsValues::Empty,
},
Self::Kwargs(kw) => Self::ArgsKargs {
args: vec![value],
kwargs: kw,
},
Self::ArgsKargs { mut args, kwargs } => {
args.insert(0, value);
Self::ArgsKargs { args, kwargs }
}
}
}
/// Splits into positional iterator and keyword values without allocating
/// for the common One/Two cases.
pub fn into_parts(self) -> (ArgPosIter, KwargsValues) {
match self {
Self::Empty => (ArgPosIter::Empty, KwargsValues::Empty),
Self::One(v) => (ArgPosIter::One(v), KwargsValues::Empty),
Self::Two(v1, v2) => (ArgPosIter::Two([v1, v2]), KwargsValues::Empty),
Self::Kwargs(kwargs) => (ArgPosIter::Empty, kwargs),
Self::ArgsKargs { args, kwargs } => (ArgPosIter::Vec(args.into_iter()), kwargs),
}
}
/// Variant of [`into_parts()`](Self::into_parts) that accepts no kwargs, returning an error if any are present.
pub fn into_pos_only(self, method_name: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<ArgPosIter> {
match self {
Self::Empty => Ok(ArgPosIter::Empty),
Self::One(v) => Ok(ArgPosIter::One(v)),
Self::Two(v1, v2) => Ok(ArgPosIter::Two([v1, v2])),
Self::Kwargs(kwargs) => {
if kwargs.is_empty() {
Ok(ArgPosIter::Empty)
} else {
Err(Self::unexpected_kwargs_error(kwargs, method_name, heap))
}
}
Self::ArgsKargs { args, kwargs } => {
if kwargs.is_empty() {
Ok(ArgPosIter::Vec(args.into_iter()))
} else {
args.drop_with_heap(heap);
Err(Self::unexpected_kwargs_error(kwargs, method_name, heap))
}
}
}
}
#[cold]
fn unexpected_kwargs_error(
kwargs: KwargsValues,
method_name: &str,
heap: &mut Heap<impl ResourceTracker>,
) -> RunError {
kwargs.drop_with_heap(heap);
ExcType::type_error_no_kwargs(method_name)
}
/// Converts the arguments into a Vec of MontyObjects.
///
/// This is used when passing arguments to external functions.
pub fn into_py_objects(
self,
vm: &mut VM<'_, '_, impl ResourceTracker>,
) -> (Vec<MontyObject>, Vec<(MontyObject, MontyObject)>) {
match self {
Self::Empty => (vec![], vec![]),
Self::One(a) => (vec![MontyObject::new(a, vm)], vec![]),
Self::Two(a1, a2) => (vec![MontyObject::new(a1, vm), MontyObject::new(a2, vm)], vec![]),
Self::Kwargs(kwargs) => (vec![], kwargs.into_py_objects(vm)),
Self::ArgsKargs { args, kwargs } => (
args.into_iter().map(|v| MontyObject::new(v, vm)).collect(),
kwargs.into_py_objects(vm),
),
}
}
/// Returns the number of positional arguments.
///
/// For `Kwargs` returns 0, for `ArgsKargs` returns only the positional args count.
fn count(&self) -> usize {
match self {
Self::Empty => 0,
Self::One(_) => 1,
Self::Two(_, _) => 2,
Self::Kwargs(_) => 0,
Self::ArgsKargs { args, .. } => args.len(),
}
}
}
impl DropWithHeap for ArgValues {
fn drop_with_heap<H: ContainsHeap>(self, heap: &mut H) {
match self {
Self::Empty => {}
Self::One(v) => v.drop_with_heap(heap),
Self::Two(v1, v2) => {
v1.drop_with_heap(heap);
v2.drop_with_heap(heap);
}
Self::Kwargs(kwargs) => {
kwargs.drop_with_heap(heap);
}
Self::ArgsKargs { args, kwargs } => {
args.drop_with_heap(heap);
kwargs.drop_with_heap(heap);
}
}
}
}
/// Iterator over positional arguments without allocation.
///
/// Supports iterating over `ArgValues::One/Two` without converting to Vec.
/// This iterator must be fully consumed OR explicitly dropped with
/// `drop_remaining_with_heap()` to maintain correct reference counts.
///
/// The iterator yields values by ownership transfer. Once a value is yielded,
/// the caller is responsible for either using it or calling `drop_with_heap()` on it.
pub(crate) enum ArgPosIter {
Empty,
One(Value),
Two([Value; 2]),
Vec(IntoIter<Value>),
}
impl ArgPosIter {
/// Returns a slice of the remaining positional arguments without consuming them.
pub fn as_slice(&self) -> &[Value] {
match self {
Self::Empty => &[],
Self::One(v) => std::slice::from_ref(v),
Self::Two(array) => array.as_slice(),
Self::Vec(iter) => iter.as_slice(),
}
}
}
impl Iterator for ArgPosIter {
type Item = Value;
#[inline]
fn next(&mut self) -> Option<Value> {
match self {
Self::Empty => None,
Self::One(_) => {
let Self::One(v) = std::mem::replace(self, Self::Empty) else {
unreachable!()
};
Some(v)
}
Self::Two(_) => {
let Self::Two([v1, v2]) = std::mem::replace(self, Self::Empty) else {
unreachable!()
};
*self = Self::One(v2);
Some(v1)
}
Self::Vec(iter) => iter.next(),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
Self::Empty => (0, Some(0)),
Self::One(_) => (1, Some(1)),
Self::Two(_) => (2, Some(2)),
Self::Vec(iter) => iter.size_hint(),
}
}
}
impl ExactSizeIterator for ArgPosIter {}
impl DropWithHeap for ArgPosIter {
fn drop_with_heap<H: ContainsHeap>(self, heap: &mut H) {
match self {
Self::Empty => {}
Self::One(v1) => v1.drop_with_heap(heap),
Self::Two(v12) => v12.drop_with_heap(heap),
Self::Vec(iter) => iter.drop_with_heap(heap),
}
}
}
/// Type for keyword arguments.
///
/// Used to capture both the case of inline keyword arguments `foo(foo=1, bar=2)`
/// and the case of a dictionary passed as a single argument `foo(**kwargs)`.
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub(crate) enum KwargsValues {
Empty,
Inline(Vec<(StringId, Value)>),
Dict(Dict),
}
impl KwargsValues {
/// Returns the number of keyword arguments.
#[must_use]
pub fn len(&self) -> usize {
match self {
Self::Empty => 0,
Self::Inline(kvs) => kvs.len(),
Self::Dict(dict) => dict.len(),
}
}
/// Returns true if there are no keyword arguments.
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Converts the arguments into a Vec of MontyObjects.
///
/// This is used when passing arguments to external functions.
fn into_py_objects(self, vm: &mut VM<'_, '_, impl ResourceTracker>) -> Vec<(MontyObject, MontyObject)> {
match self {
Self::Empty => vec![],
Self::Inline(kvs) => kvs
.into_iter()
.map(|(k, v)| {
let key = MontyObject::String(vm.interns.get_str(k).to_owned());
let value = MontyObject::new(v, vm);
(key, value)
})
.collect(),
Self::Dict(dict) => dict
.into_iter()
.map(|(k, v)| (MontyObject::new(k, vm), MontyObject::new(v, vm)))
.collect(),
}
}
/// Helper for functions which do not yet support kwargs, returns an `Err` if there are kwargs.
pub fn not_supported_yet(self, method_name: &str, heap: &mut Heap<impl ResourceTracker>) -> RunResult<()> {
if self.is_empty() {
Ok(())
} else {
self.drop_with_heap(heap);
Err(SimpleException::new_msg(
ExcType::TypeError,
format!("{method_name}() does not support keyword arguments yet"),
)
.into())
}
}
/// Parses a fixed pair of named keyword arguments with duplicate checking.
///
/// This helper is intentionally narrow: it covers the common builtin/method
/// pattern of accepting a tiny fixed keyword surface such as `key/default`
/// or `key/reverse`, while leaving positional-argument validation and any
/// post-processing to the caller.
///
/// `unexpected_keyword` formats the call-site-specific error for keywords
/// other than `kwarg1` and `kwarg2`.
pub fn parse_named_kwargs_pair(
self,
func_name: &str,
kwarg1: &str,
kwarg2: &str,
heap: &mut Heap<impl ResourceTracker>,
interns: &Interns,
unexpected_keyword: impl Fn(&str, &str) -> RunError,
) -> RunResult<(Option<Value>, Option<Value>)> {
let kwargs = self.into_iter();
defer_drop_mut!(kwargs, heap);
// Guards are reversed so that destructure can pull them.
let mut val2_guard = HeapGuard::new(None::<Value>, heap);
let (val2, heap) = val2_guard.as_parts_mut();
let mut val1_guard = HeapGuard::new(None::<Value>, heap);
let (val1, heap) = val1_guard.as_parts_mut();
for (key, value) in kwargs {
defer_drop!(key, heap);
let mut value = HeapGuard::new(value, heap);
let Some(keyword_name) = key.as_either_str(value.heap()) else {
return Err(ExcType::type_error_kwargs_nonstring_key());
};
let key_str = keyword_name.as_str(interns);
if key_str == kwarg1 {
if val1.is_some() {
return Err(ExcType::type_error_multiple_values(func_name, key_str));
}
*val1 = Some(value.into_inner());
} else if key_str == kwarg2 {
if val2.is_some() {
return Err(ExcType::type_error_multiple_values(func_name, key_str));
}
*val2 = Some(value.into_inner());
} else {
return Err(unexpected_keyword(func_name, key_str));
}
}
Ok((val1_guard.into_inner(), val2_guard.into_inner()))
}
}
impl DropWithHeap for KwargsValues {
/// Properly drops all values in the arguments, decrementing reference counts.
fn drop_with_heap<H: ContainsHeap>(self, heap: &mut H) {
match self {
Self::Empty => {}
Self::Inline(kvs) => {
for (_, v) in kvs {
v.drop_with_heap(heap);
}
}
Self::Dict(dict) => {
for (k, v) in dict {
k.drop_with_heap(heap);
v.drop_with_heap(heap);
}
}
}
}
}
impl IntoIterator for KwargsValues {
type Item = (Value, Value);
type IntoIter = KwargsValuesIter;
fn into_iter(self) -> Self::IntoIter {
match self {
Self::Empty => KwargsValuesIter::Empty,
Self::Inline(kvs) => KwargsValuesIter::Inline(kvs.into_iter()),
Self::Dict(dict) => KwargsValuesIter::Dict(dict.into_iter()),
}
}
}
/// Iterator over keyword argument (key, value) pairs.
///
/// For `Inline` kwargs, converts `StringId` keys to `Value::InternString`.
/// For `Dict` kwargs, iterates directly over the dict's entries without
/// intermediate allocation.
pub(crate) enum KwargsValuesIter {
Empty,
Inline(IntoIter<(StringId, Value)>),
Dict(DictIntoIter),
}
impl Iterator for KwargsValuesIter {
type Item = (Value, Value);
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::Empty => None,
Self::Inline(iter) => iter.next().map(|(k, v)| (Value::InternString(k), v)),
Self::Dict(iter) => iter.next(),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
Self::Empty => (0, Some(0)),
Self::Inline(iter) => iter.size_hint(),
Self::Dict(iter) => iter.size_hint(),
}
}
}
impl ExactSizeIterator for KwargsValuesIter {}
impl DropWithHeap for KwargsValuesIter {
fn drop_with_heap<H: ContainsHeap>(self, heap: &mut H) {
match self {
Self::Empty => {}
Self::Inline(iter) => {
for (_, v) in iter {
v.drop_with_heap(heap);
}
}
Self::Dict(iter) => {
for (k, v) in iter {
k.drop_with_heap(heap);
v.drop_with_heap(heap);
}
}
}
}
}
/// A keyword argument in a function call expression.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Kwarg {
pub key: Identifier,
pub value: ExprLoc,
}
/// A positional argument item in a generalized function call (PEP 448).
///
/// Used in `ArgExprs::GeneralizedCall` when a call has multiple `*unpacks`
/// or positional arguments after a `*unpack`. Each item is either a plain
/// value or a `*expr` iterable to be unpacked into the argument tuple.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub(crate) enum CallArg {
/// A plain positional argument.
Value(ExprLoc),
/// A `*expr` unpack — the iterable is spread into consecutive arguments.
Unpack(ExprLoc),
}
/// A keyword argument item in a generalized function call (PEP 448).
///
/// Used in `ArgExprs::GeneralizedCall` when a call has multiple `**unpacks`
/// or named kwargs interspersed with `**unpacks`. Duplicate keys from any
/// combination raise `TypeError` (both `f(**a, **b)` with shared keys and
/// `f(x=1, **{'x': 2})` are errors). This is enforced by `DictMerge` in
/// the compiler.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub(crate) enum CallKwarg {
/// A named keyword argument: `key=value`.
Named(Kwarg),
/// A `**expr` unpack — the mapping's entries are merged into kwargs.
Unpack(ExprLoc),
}
/// Expressions that make up a function call's arguments.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum ArgExprs {
Empty,
One(ExprLoc),
Two(ExprLoc, ExprLoc),
Args(Vec<ExprLoc>),
Kwargs(Vec<Kwarg>),
ArgsKargs {
args: Option<Vec<ExprLoc>>,
var_args: Option<ExprLoc>,
kwargs: Option<Vec<Kwarg>>,
var_kwargs: Option<ExprLoc>,
},
/// Generalized call with PEP 448 unpacking.
///
/// Used when a call has multiple `*args` unpacks, positional arguments
/// after a `*unpack`, or multiple `**kwargs` unpacks. The compiler
/// builds the args tuple incrementally using `BuildList(0)` +
/// `ListAppend`/`ListExtend` + `ListToTuple`, and the kwargs dict
/// using `BuildDict(0)` + `DictMerge` (which raises `TypeError` on
/// duplicate keys).
GeneralizedCall {
args: Vec<CallArg>,
kwargs: Vec<CallKwarg>,
},
}
impl ArgExprs {
/// Creates a `GeneralizedCall` for PEP 448 calls with multiple unpacks.
///
/// Use this when a function call has multiple `*args` unpacks, positional
/// arguments after a `*unpack`, or multiple `**kwargs` unpacks. The compiler
/// will emit `BuildList(0)` + `ListAppend`/`ListExtend` + `ListToTuple` for
/// the args tuple, and `BuildDict(0)` + `DictMerge` for the kwargs dict.
pub(crate) fn new_generalized(args: Vec<CallArg>, kwargs: Vec<CallKwarg>) -> Self {
Self::GeneralizedCall { args, kwargs }
}
/// Creates a new `ArgExprs` with optional `*args` and `**kwargs` unpacking expressions.
///
/// This is used when parsing function calls that may include `*expr` / `**expr`
/// syntax for unpacking iterables or mappings into arguments.
pub fn new_with_var_kwargs(
args: Vec<ExprLoc>,
var_args: Option<ExprLoc>,
kwargs: Vec<Kwarg>,
var_kwargs: Option<ExprLoc>,
) -> Self {
// Full generality requires ArgsKargs when we have unpacking or mixed arg/kwarg usage
if var_args.is_some() || var_kwargs.is_some() || (!kwargs.is_empty() && !args.is_empty()) {
Self::ArgsKargs {
args: if args.is_empty() { None } else { Some(args) },
var_args,
kwargs: if kwargs.is_empty() { None } else { Some(kwargs) },
var_kwargs,
}
} else if !kwargs.is_empty() {
Self::Kwargs(kwargs)
} else if args.len() > 2 {
Self::Args(args)
} else {
let mut iter = args.into_iter();
if let Some(first) = iter.next() {
if let Some(second) = iter.next() {
Self::Two(first, second)
} else {
Self::One(first)
}
} else {
Self::Empty
}
}
}
/// Applies a transformation function to all `ExprLoc` elements in the args.
///
/// This is used during the preparation phase to recursively prepare all
/// argument expressions before execution.
pub fn prepare_args(
&mut self,
mut f: impl FnMut(ExprLoc) -> Result<ExprLoc, ParseError>,
) -> Result<(), ParseError> {
// Swap self with Empty to take ownership, then rebuild
let taken = std::mem::replace(self, Self::Empty);
*self = match taken {
Self::Empty => Self::Empty,
Self::One(arg) => Self::One(f(arg)?),
Self::Two(arg1, arg2) => Self::Two(f(arg1)?, f(arg2)?),
Self::Args(args) => Self::Args(args.into_iter().map(&mut f).collect::<Result<Vec<_>, _>>()?),
Self::Kwargs(kwargs) => Self::Kwargs(
kwargs
.into_iter()
.map(|kwarg| {
Ok(Kwarg {
key: kwarg.key,
value: f(kwarg.value)?,
})
})
.collect::<Result<Vec<_>, ParseError>>()?,
),
Self::ArgsKargs {
args,
var_args,
kwargs,
var_kwargs,
} => {
let args = args
.map(|a| a.into_iter().map(&mut f).collect::<Result<Vec<_>, ParseError>>())
.transpose()?;
let var_args = var_args.map(&mut f).transpose()?;
let kwargs = kwargs
.map(|k| {
k.into_iter()
.map(|kwarg| {
Ok(Kwarg {
key: kwarg.key,
value: f(kwarg.value)?,
})
})
.collect::<Result<Vec<_>, ParseError>>()
})
.transpose()?;
let var_kwargs = var_kwargs.map(&mut f).transpose()?;
Self::ArgsKargs {
args,
var_args,
kwargs,
var_kwargs,
}
}
Self::GeneralizedCall { args, kwargs } => {
let args = args
.into_iter()
.map(|arg| match arg {
CallArg::Value(e) => Ok(CallArg::Value(f(e)?)),
CallArg::Unpack(e) => Ok(CallArg::Unpack(f(e)?)),
})
.collect::<Result<Vec<_>, ParseError>>()?;
let kwargs = kwargs
.into_iter()
.map(|kwarg| match kwarg {
CallKwarg::Named(kw) => Ok(CallKwarg::Named(Kwarg {
key: kw.key,
value: f(kw.value)?,
})),
CallKwarg::Unpack(e) => Ok(CallKwarg::Unpack(f(e)?)),
})
.collect::<Result<Vec<_>, ParseError>>()?;
Self::GeneralizedCall { args, kwargs }
}
};
Ok(())
}
}
================================================
FILE: crates/monty/src/asyncio.rs
================================================
//! Async/await support types for Monty.
//!
//! This module contains all async-related types including coroutines, futures,
//! and task identifiers. The host acts as the event loop - external function
//! calls return `ExternalFuture` objects that can be awaited.
use crate::{heap::HeapId, intern::FunctionId, value::Value};
/// Unique identifier for external function calls.
///
/// Sequential integers allocated by the scheduler. Used to correlate
/// external function calls with their results when the host resolves them.
/// The counter always increments, even for sync resolution, to keep IDs unique.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) struct CallId(u32);
impl CallId {
/// Creates a new CallId from a raw value.
#[inline]
pub fn new(id: u32) -> Self {
Self(id)
}
/// Returns the raw u32 value.
#[inline]
pub fn raw(self) -> u32 {
self.0
}
}
/// Unique identifier for an async task.
///
/// Sequential integers allocated by the scheduler. Task 0 is always the main task
/// which uses the VM's stack/frames directly. Spawned tasks (1+) store their own context,
/// hence `TaskId::default()` is the main task.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) struct TaskId(u32);
impl TaskId {
/// Creates a new TaskId from a raw value.
#[inline]
pub fn new(id: u32) -> Self {
Self(id)
}
/// Returns the raw u32 value.
#[inline]
pub fn raw(self) -> u32 {
self.0
}
/// Returns true if this is the main task (task 0).
#[inline]
pub fn is_main(self) -> bool {
self.0 == 0
}
}
/// Coroutine execution state (single-shot semantics).
///
/// Coroutines in Monty follow single-shot semantics - they can only be awaited once.
/// This differs from Python generators which can be resumed multiple times.
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub(crate) enum CoroutineState {
/// Coroutine has been created but not yet awaited.
New,
/// Coroutine is currently executing (has been awaited).
Running,
/// Coroutine has finished execution.
Completed,
}
/// A coroutine object representing an async function call result.
///
/// Created when an `async def` function is called. Argument binding happens at call time;
/// awaiting the coroutine starts execution. Coroutines use single-shot semantics -
/// they can only be awaited once.
///
/// # Namespace Layout
///
/// The `namespace` vector is pre-sized to match the function's namespace size and contains:
/// ```text
/// [params...][cell_vars...][free_vars...][locals...]
/// ```
/// - Parameter slots are filled with bound argument values at call time
/// - Cell/free var slots contain `Value::Ref` to captured cells
/// - Local slots start as `Value::Undefined`
///
/// When the coroutine is awaited, these values are pushed onto the VM's stack
/// as inline locals, and a new frame is pushed to execute the async function body.
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub(crate) struct Coroutine {
/// The async function to execute.
pub func_id: FunctionId,
/// Pre-bound namespace values (sized to function namespace).
/// Contains bound parameters, captured cells, and uninitialized locals.
pub namespace: Vec<Value>,
/// Current execution state.
pub state: CoroutineState,
}
impl Coroutine {
/// Creates a new coroutine for an async function call.
///
/// # Arguments
/// * `func_id` - The async function to execute
/// * `namespace` - Pre-bound namespace with parameters and captured variables
pub fn new(func_id: FunctionId, namespace: Vec<Value>) -> Self {
Self {
func_id,
namespace,
state: CoroutineState::New,
}
}
}
/// An item that can be gathered - either a coroutine or an external future.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub(crate) enum GatherItem {
/// A coroutine to spawn as a task.
Coroutine(HeapId),
/// An external future to wait for resolution.
ExternalFuture(CallId),
}
/// A gather() result tracking multiple coroutines/tasks and external futures.
///
/// Created by `asyncio.gather(*awaitables)`. Does NOT spawn tasks immediately -
/// tasks are spawned when the GatherFuture is awaited in Await.
///
/// # Lifecycle
///
/// 1. **Creation**: `gather(coro1, coro2, ...)` stores coroutine HeapIds and external CallIds
/// 2. **Await**: `await gather_future` spawns tasks and blocks the current task
/// 3. **Completion**: As tasks/futures complete, results are stored in order
/// 4. **Return**: When all items complete, returns list of results
///
/// # Error Handling
///
/// On any task failure, sibling tasks are cancelled and the exception propagates
/// to the task that awaited the gather.
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub(crate) struct GatherFuture {
/// Items to gather (coroutines or external futures).
pub items: Vec<GatherItem>,
/// TaskIds of spawned tasks (only for coroutine items, set when awaited).
/// Length matches the number of Coroutine items.
pub task_ids: Vec<TaskId>,
/// Results from each item, in order (filled as items complete).
/// Indices align with `items`.
pub results: Vec<Option<Value>>,
/// Task waiting on this gather (set when awaited).
pub waiter: Option<TaskId>,
/// CallIds of external futures we're waiting on.
/// Used to check if all external futures have resolved.
pub pending_calls: Vec<CallId>,
}
impl GatherFuture {
/// Creates a new GatherFuture with the given items.
///
/// # Arguments
/// * `items` - Coroutines or external futures to run concurrently
pub fn new(items: Vec<GatherItem>) -> Self {
let count = items.len();
Self {
items,
task_ids: Vec::new(),
results: (0..count).map(|_| None).collect(),
waiter: None,
pending_calls: Vec::new(),
}
}
/// Returns the number of items to gather.
#[inline]
pub fn item_count(&self) -> usize {
self.items.len()
}
}
================================================
FILE: crates/monty/src/builtins/abs.rs
================================================
//! Implementation of the abs() builtin function.
use num_bigint::BigInt;
use num_traits::Signed;
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult, SimpleException},
heap::HeapData,
resource::ResourceTracker,
types::{LongInt, PyTrait},
value::Value,
};
/// Implementation of the abs() builtin function.
///
/// Returns the absolute value of a number. Works with integers, floats, and LongInts.
/// For `i64::MIN`, which overflows on negation, promotes to LongInt.
pub fn builtin_abs(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let value = args.get_one_arg("abs", vm.heap)?;
defer_drop!(value, vm);
match value {
Value::Int(n) => {
// Handle potential overflow for i64::MIN → promote to LongInt
if let Some(abs_val) = n.checked_abs() {
Ok(Value::Int(abs_val))
} else {
// i64::MIN.abs() overflows, promote to LongInt
let bi = BigInt::from(*n).abs();
Ok(LongInt::new(bi).into_value(vm.heap)?)
}
}
Value::Float(f) => Ok(Value::Float(f.abs())),
Value::Bool(b) => Ok(Value::Int(i64::from(*b))),
Value::Ref(id) => {
if let HeapData::LongInt(li) = vm.heap.get(*id) {
Ok(li.abs().into_value(vm.heap)?)
} else {
Err(SimpleException::new_msg(
ExcType::TypeError,
format!("bad operand type for abs(): '{}'", value.py_type(vm.heap)),
)
.into())
}
}
_ => Err(SimpleException::new_msg(
ExcType::TypeError,
format!("bad operand type for abs(): '{}'", value.py_type(vm.heap)),
)
.into()),
}
}
================================================
FILE: crates/monty/src/builtins/all.rs
================================================
//! Implementation of the all() builtin function.
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop, defer_drop_mut,
exception_private::RunResult,
resource::ResourceTracker,
types::{MontyIter, PyTrait},
value::Value,
};
/// Implementation of the all() builtin function.
///
/// Returns True if all elements of the iterable are true (or if the iterable is empty).
/// Short-circuits on the first falsy value.
pub fn builtin_all(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let iterable = args.get_one_arg("all", vm.heap)?;
let iter = MontyIter::new(iterable, vm)?;
defer_drop_mut!(iter, vm);
while let Some(item) = iter.for_next(vm)? {
defer_drop!(item, vm);
if !item.py_bool(vm) {
return Ok(Value::Bool(false));
}
}
Ok(Value::Bool(true))
}
================================================
FILE: crates/monty/src/builtins/any.rs
================================================
//! Implementation of the any() builtin function.
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop, defer_drop_mut,
exception_private::RunResult,
resource::ResourceTracker,
types::{MontyIter, PyTrait},
value::Value,
};
/// Implementation of the any() builtin function.
///
/// Returns True if any element of the iterable is true.
/// Returns False for an empty iterable. Short-circuits on the first truthy value.
pub fn builtin_any(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let iterable = args.get_one_arg("any", vm.heap)?;
let iter = MontyIter::new(iterable, vm)?;
defer_drop_mut!(iter, vm);
while let Some(item) = iter.for_next(vm)? {
defer_drop!(item, vm);
if item.py_bool(vm) {
return Ok(Value::Bool(true));
}
}
Ok(Value::Bool(false))
}
================================================
FILE: crates/monty/src/builtins/bin.rs
================================================
//! Implementation of the bin() builtin function.
use num_bigint::BigInt;
use num_traits::Signed;
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult},
heap::HeapData,
resource::ResourceTracker,
types::{PyTrait, Str},
value::Value,
};
/// Implementation of the bin() builtin function.
///
/// Converts an integer to a binary string prefixed with '0b'.
/// Supports both i64 and BigInt integers.
pub fn builtin_bin(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let value = args.get_one_arg("bin", vm.heap)?;
defer_drop!(value, vm);
match value {
Value::Int(n) => {
let abs_digits = format!("{:b}", n.unsigned_abs());
let prefix = if *n < 0 { "-0b" } else { "0b" };
let heap_id = vm
.heap
.allocate(HeapData::Str(Str::new(format!("{prefix}{abs_digits}"))))?;
Ok(Value::Ref(heap_id))
}
Value::Bool(b) => {
let s = if *b { "0b1" } else { "0b0" };
let heap_id = vm.heap.allocate(HeapData::Str(Str::new(s.to_string())))?;
Ok(Value::Ref(heap_id))
}
Value::Ref(id) => {
if let HeapData::LongInt(li) = vm.heap.get(*id) {
let bin_str = format_bigint_bin(li.inner());
let heap_id = vm.heap.allocate(HeapData::Str(Str::new(bin_str)))?;
Ok(Value::Ref(heap_id))
} else {
Err(ExcType::type_error_not_integer(value.py_type(vm.heap)))
}
}
_ => Err(ExcType::type_error_not_integer(value.py_type(vm.heap))),
}
}
/// Formats a BigInt as a binary string with '0b' prefix.
fn format_bigint_bin(bi: &BigInt) -> String {
let is_negative = bi.is_negative();
let abs_bi = bi.abs();
let bin_digits = format!("{abs_bi:b}");
let prefix = if is_negative { "-0b" } else { "0b" };
format!("{prefix}{bin_digits}")
}
================================================
FILE: crates/monty/src/builtins/chr.rs
================================================
//! Implementation of the chr() builtin function.
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult, SimpleException},
resource::ResourceTracker,
types::{PyTrait, str::allocate_char},
value::Value,
};
/// Implementation of the chr() builtin function.
///
/// Returns a string representing a character whose Unicode code point is the integer.
/// The valid range for the argument is from 0 through 1,114,111 (0x10FFFF).
pub fn builtin_chr(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let value = args.get_one_arg("chr", vm.heap)?;
defer_drop!(value, vm);
match value {
Value::Int(n) => {
if *n < 0 || *n > 0x0010_FFFF {
Err(SimpleException::new_msg(ExcType::ValueError, "chr() arg not in range(0x110000)").into())
} else if let Some(c) = char::from_u32(u32::try_from(*n).expect("chr() range check failed")) {
Ok(allocate_char(c, vm.heap)?)
} else {
// This shouldn't happen for valid Unicode range, but handle it
Err(SimpleException::new_msg(ExcType::ValueError, "chr() arg not in range(0x110000)").into())
}
}
Value::Bool(b) => {
// bool is subclass of int
let c = if *b { '\x01' } else { '\x00' };
Ok(allocate_char(c, vm.heap)?)
}
_ => {
let type_name = value.py_type(vm.heap);
Err(SimpleException::new_msg(
ExcType::TypeError,
format!("an integer is required (got type {type_name})"),
)
.into())
}
}
}
================================================
FILE: crates/monty/src/builtins/divmod.rs
================================================
//! Implementation of the divmod() builtin function.
use num_bigint::BigInt;
use num_integer::Integer;
use smallvec::smallvec;
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult, SimpleException},
heap::HeapData,
resource::{ResourceTracker, check_div_size},
types::{LongInt, PyTrait, allocate_tuple},
value::{Value, floor_divmod},
};
/// Implementation of the divmod() builtin function.
///
/// Returns a tuple (quotient, remainder) from integer division.
/// Equivalent to (a // b, a % b).
pub fn builtin_divmod(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let (a, b) = args.get_two_args("divmod", vm.heap)?;
let a = super::round::normalize_bool_to_int(a);
let b = super::round::normalize_bool_to_int(b);
defer_drop!(a, vm);
defer_drop!(b, vm);
let heap = &mut *vm.heap;
match (a, b) {
(Value::Int(x), Value::Int(y)) => {
if *y == 0 {
Err(ExcType::divmod_by_zero())
} else if let Some((quot, rem)) = floor_divmod(*x, *y) {
Ok(allocate_tuple(smallvec![Value::Int(quot), Value::Int(rem)], heap)?)
} else {
// Overflow - promote to BigInt
check_div_size(64, heap.tracker())?;
let (quot, rem) = bigint_floor_divmod(&BigInt::from(*x), &BigInt::from(*y));
let quot_val = LongInt::new(quot).into_value(heap)?;
let rem_val = LongInt::new(rem).into_value(heap)?;
Ok(allocate_tuple(smallvec![quot_val, rem_val], heap)?)
}
}
(Value::Int(x), Value::Ref(id)) => {
if let HeapData::LongInt(li) = heap.get(*id) {
if li.is_zero() {
Err(ExcType::divmod_by_zero())
} else {
let x_bi = BigInt::from(*x);
let (quot, rem) = bigint_floor_divmod(&x_bi, li.inner());
let quot_val = LongInt::new(quot).into_value(heap)?;
let rem_val = LongInt::new(rem).into_value(heap)?;
Ok(allocate_tuple(smallvec![quot_val, rem_val], heap)?)
}
} else {
let a_type = a.py_type(heap);
let b_type = b.py_type(heap);
Err(SimpleException::new_msg(
ExcType::TypeError,
format!("unsupported operand type(s) for divmod(): '{a_type}' and '{b_type}'"),
)
.into())
}
}
(Value::Ref(id), Value::Int(y)) => {
if let HeapData::LongInt(li) = heap.get(*id) {
if *y == 0 {
Err(ExcType::divmod_by_zero())
} else {
let y_bi = BigInt::from(*y);
let (quot, rem) = bigint_floor_divmod(li.inner(), &y_bi);
let quot_val = LongInt::new(quot).into_value(heap)?;
let rem_val = LongInt::new(rem).into_value(heap)?;
Ok(allocate_tuple(smallvec![quot_val, rem_val], heap)?)
}
} else {
let a_type = a.py_type(heap);
let b_type = b.py_type(heap);
Err(SimpleException::new_msg(
ExcType::TypeError,
format!("unsupported operand type(s) for divmod(): '{a_type}' and '{b_type}'"),
)
.into())
}
}
(Value::Ref(id1), Value::Ref(id2)) => {
let x_bi = if let HeapData::LongInt(li) = heap.get(*id1) {
li.inner().clone()
} else {
let a_type = a.py_type(heap);
let b_type = b.py_type(heap);
return Err(SimpleException::new_msg(
ExcType::TypeError,
format!("unsupported operand type(s) for divmod(): '{a_type}' and '{b_type}'"),
)
.into());
};
if let HeapData::LongInt(li) = heap.get(*id2) {
if li.is_zero() {
Err(ExcType::divmod_by_zero())
} else {
let (quot, rem) = bigint_floor_divmod(&x_bi, li.inner());
let quot_val = LongInt::new(quot).into_value(heap)?;
let rem_val = LongInt::new(rem).into_value(heap)?;
Ok(allocate_tuple(smallvec![quot_val, rem_val], heap)?)
}
} else {
let a_type = a.py_type(heap);
let b_type = b.py_type(heap);
Err(SimpleException::new_msg(
ExcType::TypeError,
format!("unsupported operand type(s) for divmod(): '{a_type}' and '{b_type}'"),
)
.into())
}
}
(Value::Float(x), Value::Float(y)) => {
if *y == 0.0 {
Err(ExcType::divmod_by_zero())
} else {
let quot = (x / y).floor();
let rem = x - quot * y;
Ok(allocate_tuple(smallvec![Value::Float(quot), Value::Float(rem)], heap)?)
}
}
(Value::Int(x), Value::Float(y)) => {
if *y == 0.0 {
Err(ExcType::divmod_by_zero())
} else {
let xf = *x as f64;
let quot = (xf / y).floor();
let rem = xf - quot * y;
Ok(allocate_tuple(smallvec![Value::Float(quot), Value::Float(rem)], heap)?)
}
}
(Value::Float(x), Value::Int(y)) => {
if *y == 0 {
Err(ExcType::divmod_by_zero())
} else {
let yf = *y as f64;
let quot = (x / yf).floor();
let rem = x - quot * yf;
Ok(allocate_tuple(smallvec![Value::Float(quot), Value::Float(rem)], heap)?)
}
}
_ => {
let a_type = a.py_type(heap);
let b_type = b.py_type(heap);
Err(SimpleException::new_msg(
ExcType::TypeError,
format!("unsupported operand type(s) for divmod(): '{a_type}' and '{b_type}'"),
)
.into())
}
}
}
/// Computes Python-style floor division and modulo for BigInts.
///
/// Uses `div_mod_floor` from num_integer for correct floor semantics.
fn bigint_floor_divmod(a: &BigInt, b: &BigInt) -> (BigInt, BigInt) {
a.div_mod_floor(b)
}
================================================
FILE: crates/monty/src/builtins/enumerate.rs
================================================
//! Implementation of the enumerate() builtin function.
use smallvec::smallvec;
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop, defer_drop_mut,
exception_private::{ExcType, RunResult, SimpleException},
heap::HeapData,
resource::ResourceTracker,
types::{List, MontyIter, PyTrait, allocate_tuple},
value::Value,
};
/// Implementation of the enumerate() builtin function.
///
/// Returns a list of (index, value) tuples.
/// Note: In Python this returns an iterator, but we return a list for simplicity.
pub fn builtin_enumerate(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let (iterable, start) = args.get_one_two_args("enumerate", vm.heap)?;
let iter = MontyIter::new(iterable, vm)?;
defer_drop_mut!(iter, vm);
defer_drop!(start, vm);
// Get start index (default 0)
let mut index: i64 = match start {
Some(Value::Int(n)) => *n,
Some(Value::Bool(b)) => i64::from(*b),
Some(v) => {
let type_name = v.py_type(vm.heap);
return Err(SimpleException::new_msg(
ExcType::TypeError,
format!("'{type_name}' object cannot be interpreted as an integer"),
)
.into());
}
None => 0,
};
let mut result: Vec<Value> = Vec::new();
while let Some(item) = iter.for_next(vm)? {
// Create tuple (index, item)
let tuple_val = allocate_tuple(smallvec![Value::Int(index), item], vm.heap)?;
result.push(tuple_val);
index += 1;
}
let heap_id = vm.heap.allocate(HeapData::List(List::new(result)))?;
Ok(Value::Ref(heap_id))
}
================================================
FILE: crates/monty/src/builtins/filter.rs
================================================
//! Implementation of the filter() builtin function.
//!
//! This module provides the filter() builtin which filters elements from an iterable
//! based on a predicate function. The implementation supports:
//! - `None` as predicate (filters falsy values)
//! - Builtin functions (len, abs, etc.)
//! - Type constructors (int, str, float, etc.)
//! - User-defined functions (via `vm.evaluate_function`)
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop, defer_drop_mut,
exception_private::RunResult,
heap::{HeapData, HeapGuard},
resource::ResourceTracker,
types::{List, MontyIter, PyTrait},
value::Value,
};
/// Implementation of the filter() builtin function.
///
/// Filters elements from an iterable based on a predicate function.
/// If the predicate is None, filters out falsy values.
///
/// Note: In Python this returns an iterator, but we return a list for simplicity.
///
/// Examples:
/// ```python
/// filter(lambda x: x > 0, [-1, 0, 1, 2]) # [1, 2]
/// filter(None, [0, 1, False, True, '']) # [1, True]
/// ```
pub fn builtin_filter(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let (function, iterable) = args.get_two_args("filter", vm.heap)?;
defer_drop!(function, vm);
let iter = MontyIter::new(iterable, vm)?;
defer_drop_mut!(iter, vm);
let out: Vec<Value> = Vec::new();
let mut out_guard = HeapGuard::new(out, vm);
let (out, vm) = out_guard.as_parts_mut();
while let Some(item) = iter.for_next(vm)? {
let mut item_guard = HeapGuard::new(item, vm);
let (item, vm) = item_guard.as_parts_mut();
let should_include = if let Value::None = function {
// No predicate - use truthiness of element
item.py_bool(vm)
} else {
// Clone for predicate call - the clone is consumed by evaluate_function
let item_for_predicate = item.clone_with_heap(vm);
let result = vm.evaluate_function("filter()", function, ArgValues::One(item_for_predicate))?;
let is_truthy = result.py_bool(vm);
result.drop_with_heap(vm);
is_truthy
};
if should_include {
out.push(item_guard.into_inner());
}
}
let (out, vm) = out_guard.into_parts();
let heap_id = vm.heap.allocate(HeapData::List(List::new(out)))?;
Ok(Value::Ref(heap_id))
}
================================================
FILE: crates/monty/src/builtins/getattr.rs
================================================
//! Implementation of the getattr() builtin function.
use crate::{
ExcType,
args::ArgValues,
bytecode::{CallResult, VM},
defer_drop,
exception_private::{RunResult, SimpleException},
resource::ResourceTracker,
types::PyTrait,
value::Value,
};
/// Implementation of the getattr() builtin function.
///
/// Returns the value of the named attribute of an object.
/// If the attribute doesn't exist and a default is provided, returns the default.
/// If no default is provided and the attribute doesn't exist, raises AttributeError.
///
/// Note: name must be a string. Per Python docs, "Since private name mangling happens
/// at compilation time, one must manually mangle a private attribute's (attributes with
/// two leading underscores) name in order to retrieve it with getattr()."
///
/// Examples:
/// ```python
/// getattr(obj, 'x') # Get obj.x
/// getattr(obj, 'y', None) # Get obj.y or None if not found
/// getattr(module, 'function') # Get module.function
/// ```
pub fn builtin_getattr(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let positional = args.into_pos_only("getattr", vm.heap)?;
defer_drop!(positional, vm);
let (object, name, default) = match positional.as_slice() {
too_few @ ([] | [_]) => return Err(ExcType::type_error_at_least("getattr", 2, too_few.len())),
[object, name] => (object, name, None),
[object, name, default] => (object, name, Some(default)),
too_many => return Err(ExcType::type_error_at_most("getattr", 3, too_many.len())),
};
let Some(attr) = name.as_either_str(vm.heap) else {
let ty = name.py_type(vm.heap);
return Err(
SimpleException::new_msg(ExcType::TypeError, format!("attribute name must be string, not '{ty}'")).into(),
);
};
match object.py_getattr(&attr, vm) {
Ok(CallResult::Value(value)) => Ok(value),
Ok(_) => {
// getattr() only retrieves attribute values — OS calls, external calls,
// method calls, and awaits are not supported here
//
// TODO: might need to support this case?
Err(SimpleException::new_msg(ExcType::TypeError, "getattr(): attribute is not a simple value").into())
}
Err(e) => {
if let Some(d) = default {
Ok(d.clone_with_heap(vm))
} else {
Err(e)
}
}
}
}
================================================
FILE: crates/monty/src/builtins/hash.rs
================================================
//! Implementation of the hash() builtin function.
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult},
resource::ResourceTracker,
types::PyTrait,
value::Value,
};
/// Implementation of the hash() builtin function.
///
/// Returns the hash value of an object (if it has one).
/// Raises TypeError for unhashable types like lists and dicts.
pub fn builtin_hash(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let value = args.get_one_arg("hash", vm.heap)?;
defer_drop!(value, vm);
match value.py_hash(vm.heap, vm.interns)? {
Some(hash) => {
// Python's hash() returns a signed integer; reinterpret bits for large values
let hash_i64 = i64::from_ne_bytes(hash.to_ne_bytes());
Ok(Value::Int(hash_i64))
}
None => Err(ExcType::type_error_unhashable(value.py_type(vm.heap))),
}
}
================================================
FILE: crates/monty/src/builtins/hex.rs
================================================
//! Implementation of the hex() builtin function.
use num_bigint::BigInt;
use num_traits::Signed;
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult},
heap::HeapData,
resource::ResourceTracker,
types::{PyTrait, Str},
value::Value,
};
/// Implementation of the hex() builtin function.
///
/// Converts an integer to a lowercase hexadecimal string prefixed with '0x'.
/// Supports both i64 and BigInt integers.
pub fn builtin_hex(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let value = args.get_one_arg("hex", vm.heap)?;
defer_drop!(value, vm);
let heap = &mut *vm.heap;
match value {
Value::Int(n) => {
let abs_digits = format!("{:x}", n.unsigned_abs());
let prefix = if *n < 0 { "-0x" } else { "0x" };
let heap_id = heap.allocate(HeapData::Str(Str::new(format!("{prefix}{abs_digits}"))))?;
Ok(Value::Ref(heap_id))
}
Value::Bool(b) => {
let s = if *b { "0x1" } else { "0x0" };
let heap_id = heap.allocate(HeapData::Str(Str::new(s.to_string())))?;
Ok(Value::Ref(heap_id))
}
Value::Ref(id) => {
if let HeapData::LongInt(li) = heap.get(*id) {
let hex_str = format_bigint_hex(li.inner());
let heap_id = heap.allocate(HeapData::Str(Str::new(hex_str)))?;
Ok(Value::Ref(heap_id))
} else {
Err(ExcType::type_error_not_integer(value.py_type(heap)))
}
}
_ => Err(ExcType::type_error_not_integer(value.py_type(heap))),
}
}
/// Formats a BigInt as a hexadecimal string with '0x' prefix.
fn format_bigint_hex(bi: &BigInt) -> String {
let is_negative = bi.is_negative();
let abs_bi = bi.abs();
let hex_digits = format!("{abs_bi:x}");
let prefix = if is_negative { "-0x" } else { "0x" };
format!("{prefix}{hex_digits}")
}
================================================
FILE: crates/monty/src/builtins/id.rs
================================================
//! Implementation of the id() builtin function.
use crate::{
args::ArgValues, bytecode::VM, defer_drop, exception_private::RunResult, resource::ResourceTracker, value::Value,
};
/// Implementation of the id() builtin function.
///
/// Returns the identity of an object (unique integer for the object's lifetime).
pub fn builtin_id(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let value = args.get_one_arg("id", vm.heap)?;
defer_drop!(value, vm);
let id = value.id();
// Python's id() returns a signed integer; reinterpret bits for large values
// On 64-bit: large addresses wrap to negative; on 32-bit: always fits positive
#[expect(
clippy::cast_possible_wrap,
reason = "Python id() returns signed; wrapping intentional"
)]
let id_i64 = id as i64;
Ok(Value::Int(id_i64))
}
================================================
FILE: crates/monty/src/builtins/isinstance.rs
================================================
//! Implementation of the isinstance() builtin function.
use super::Builtins;
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult},
heap::{Heap, HeapData},
resource::ResourceTracker,
types::{PyTrait, Type},
value::Value,
};
/// Implementation of the isinstance() builtin function.
///
/// Checks if an object is an instance of a class or a tuple of classes.
pub fn builtin_isinstance(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let (obj, classinfo) = args.get_two_args("isinstance", vm.heap)?;
defer_drop!(obj, vm);
defer_drop!(classinfo, vm);
let heap = &mut *vm.heap;
let obj_type = obj.py_type(heap);
match isinstance_check(obj_type, classinfo, heap) {
Ok(result) => Ok(Value::Bool(result)),
Err(()) => Err(ExcType::isinstance_arg2_error()),
}
}
/// Recursively checks if obj_type matches classinfo for isinstance().
///
/// Returns `Ok(true)` if the type matches, `Ok(false)` if it doesn't,
/// or `Err(())` if classinfo is invalid (not a type or tuple of types).
///
/// Supports:
/// - Single types: `isinstance(x, int)`
/// - Exception types: `isinstance(err, ValueError)`
/// - Exception hierarchy: `isinstance(err, LookupError)` for KeyError/IndexError
/// - Nested tuples: `isinstance(x, (int, (str, bytes)))`
fn isinstance_check(obj_type: Type, classinfo: &Value, heap: &Heap<impl ResourceTracker>) -> Result<bool, ()> {
match classinfo {
// Single type: isinstance(x, int)
Value::Builtin(Builtins::Type(t)) => Ok(obj_type.is_instance_of(*t)),
// Exception type: isinstance(err, ValueError) or isinstance(err, LookupError)
Value::Builtin(Builtins::ExcType(handler_type)) => {
// Check exception hierarchy using is_subclass_of
Ok(matches!(obj_type, Type::Exception(exc_type) if exc_type.is_subclass_of(*handler_type)))
}
// Tuple of types (possibly nested): isinstance(x, (int, (str, bytes)))
Value::Ref(id) => {
if let HeapData::Tuple(tuple) = heap.get(*id) {
for v in tuple.as_slice() {
if isinstance_check(obj_type, v, heap)? {
return Ok(true);
}
}
Ok(false)
} else {
Err(()) // Not a tuple - invalid
}
}
_ => Err(()), // Invalid classinfo
}
}
================================================
FILE: crates/monty/src/builtins/len.rs
================================================
//! Implementation of the len() builtin function.
use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult, SimpleException},
resource::ResourceTracker,
types::PyTrait,
value::Value,
};
/// Implementation of the len() builtin function.
///
/// Returns the length of an object (number of items in a container).
pub fn builtin_len(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let value = args.get_one_arg("len", vm.heap)?;
defer_drop!(value, vm);
if let Some(len) = value.py_len(vm) {
Ok(Value::Int(i64::try_from(len).expect("len exceeds i64::MAX")))
} else {
let type_name = value.py_type(vm.heap);
Err(SimpleException::new_msg(ExcType::TypeError, format!("object of type '{type_name}' has no len()")).into())
}
}
================================================
FILE: crates/monty/src/builtins/map.rs
================================================
//! Implementation of the map() builtin function.
use crate::{
args::{ArgValues, KwargsValues},
bytecode::VM,
defer_drop, defer_drop_mut,
exception_private::{ExcType, RunResult, SimpleException},
heap::{DropWithHeap, HeapData},
resource::ResourceTracker,
types::{List, MontyIter},
value::Value,
};
/// Implementation of the map() builtin function.
///
/// Applies a function to every item of one or more iterables and returns a list of results.
/// With multiple iterables, stops when the shortest iterable is exhausted.
///
/// Note: In Python this returns an iterator, but we return a list for simplicity.
/// Note: The `strict=` parameter is not yet supported.
///
/// Examples:
/// ```python
/// map(abs, [-1, 0, 1, 2]) # [1, 0, 1, 2]
/// map(pow, [2, 3], [3, 2]) # [8, 9]
/// map(str, [1, 2, 3]) # ['1', '2', '3']
/// ```
pub fn builtin_map(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
let (positional, kwargs) = args.into_parts();
defer_drop_mut!(positional, vm);
kwargs.not_supported_yet("map", vm.heap)?;
if positional.len() < 2 {
return Err(SimpleException::new_msg(ExcType::TypeError, "map() must have at least two arguments.").into());
}
let function = positional.next().unwrap();
defer_drop!(function, vm);
let first_iterable = positional.next().expect("checked length above");
let first_iter = MontyIter::new(first_iterable, vm)?;
defer_drop_mut!(first_iter, vm);
let extra_iterators: Vec<MontyIter> = Vec::with_capacity(positional.len());
defer_drop_mut!(extra_iterators, vm);
for iterable in positional {
extra_iterators.push(MontyIter::new(iterable, vm)?);
}
let mut out = Vec::with_capacity(first_iter.size_hint(vm.heap));
// map function over iterables until the shortest iter is exhausted
match extra_iterators.as_mut_slice() {
// map(f, iter)
[] => {
while let Some(item) = first_iter.for_next(vm)? {
let args = ArgValues::One(item);
out.push(vm.evaluate_function("map()", function, args)?);
}
}
// map(f, iter1, iter2)
[single] => {
while let Some(arg1) = first_iter.for_next(vm)? {
let Some(arg2) = single.for_next(vm)? else {
arg1.drop_with_heap(vm);
break;
};
let args = ArgValues::Two(arg1, arg2);
out.push(vm.evaluate_function("map()", function, args)?);
}
}
// map(f, iter1, iter2, *iterables)
multiple => 'outer: loop {
let mut items = Vec::with_capacity(1 + multiple.len());
for iter in std::iter::once(&mut *first_iter).chain(multiple.iter_mut()) {
if let Some(item) = iter.for_next(vm)? {
items.push(item);
} else {
items.drop_with_heap(vm);
break 'outer;
}
}
let args = ArgValues::ArgsKargs {
args: items,
kwargs: KwargsValues::Empty,
};
out.push(vm.evaluate_function("map()", function, args)?);
},
}
let heap_id = vm.heap.allocate(HeapData::List(List::new(out)))?;
Ok(Value::Ref(heap_id))
}
================================================
FILE: crates/monty/src/builtins/min_max.rs
================================================
//! Implementation of the min() and max() builtin functions.
use std::cmp::Ordering;
use crate::{
args::{ArgValues, KwargsValues},
bytecode::VM,
defer_drop, defer_drop_mut,
exception_private::{ExcType, RunError, RunResult, SimpleException},
heap::{Heap, HeapGuard},
heap_traits::DropWithHeap,
resource::ResourceTracker,
types::{MontyIter, PyTrait},
value::Value,
};
/// Implementation of the min() builtin function.
///
/// Returns the smallest item in an iterable or the smallest of two or more arguments.
/// Supports two forms:
/// - `min(iterable)` - returns smallest item from iterable
/// - `min(arg1, arg2, ...)` - returns smallest of the arguments
pub fn builtin_min(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
builtin_min_max(vm, args, true)
}
/// Implementation of the max() builtin function.
///
/// Returns the largest item in an iterable or the largest of two or more arguments.
/// Supports two forms:
/// - `max(iterable)` - returns largest item from iterable
/// - `max(arg1, arg2, ...)` - returns largest of the arguments
pub fn builtin_max(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
builtin_min_max(vm, args, false)
}
/// Shared implementation for min() and max().
///
/// When `is_min` is true, returns the minimum; otherwise returns the maximum.
fn builtin_min_max(vm: &mut VM<'_, '_, impl ResourceTracker>, args: ArgValues, is_min: bool) -> RunResult<Value> {
let func_name = if is_min { "min" } else { "max" };
let key_context = if is_min {
"min() key argument"
} else {
"max() key argument"
};
let (positional, kwargs) = args.into_parts();
defer_drop_mut!(positional, vm);
let Some(first_arg) = positional.next() else {
kwargs.drop_with_heap(vm);
return Err(SimpleException::new_msg(
ExcType::TypeError,
format!("{func_name} expected at least 1 argument, got 0"),
)
.into());
};
let mut first_arg_guard = HeapGuard::new(first_arg, vm);
let (key_fn, default_value) = parse_min_max_kwargs(kwargs, func_name, first_arg_guard.heap())?;
let (first_arg, vm) = first_arg_guard.into_parts();
defer_drop!(key_fn, vm);
let mut default_guard = HeapGuard::new(default_value, vm);
let (default_value, vm) = default_guard.as_parts_mut();
// decide what to do based on remaining arguments
if positional.len() == 0 {
// Single argument: iterate over it
let iter = MontyIter::new(first_arg, vm)?;
defer_drop_mut!(iter, vm);
let Some(result) = iter.for_next(vm)? else {
if let Some(default) = default_value.take() {
return Ok(default);
}
return Err(SimpleException::new_msg(
ExcType::ValueError,
format!("{func_name}() iterable argument is empty"),
)
.into());
};
if let Some(key_fn) = key_fn {
let mut result_guard = HeapGuard::new(result, vm);
{
let (result, vm) = result_guard.as_parts_mut();
let result_key = evaluate_key(result.clone_with_heap(vm), key_fn, key_context, vm)?;
let mut result_key_guard = HeapGuard::new(result_key, vm);
{
let (result_key, vm) = result_key_guard.as_parts_mut();
while let Some(item) = iter.for_next(vm)? {
defer_drop_mut!(item, vm);
let item_key = evaluate_key(item.clone_with_heap(vm), key_fn, key_context, vm)?;
defer_drop_mut!(item_key, vm);
if candidate_wins(result_key, item_key, is_min, vm)? {
std::mem::swap(result, item);
std::mem::swap(result_key, item_key);
}
}
}
let result_key = result_key_guard.into_inner();
result_key.drop_with_heap(vm);
}
Ok(result_guard.into_inner())
} else {
let mut result_guard = HeapGuard::new(result, vm);
let (result, vm) = result_guard.as_parts_mut();
while let Some(item) = iter.for_next(vm)? {
defer_drop_mut!(item, vm);
if candidate_wins(result, item, is_min, vm)? {
std::mem::swap(result, item);
}
}
Ok(result_guard.into_inner())
}
} else {
// Multiple arguments: compare them directly
if default_value.is_some() {
first_arg.drop_with_heap(vm);
return Err(default_with_multiple_args(func_name));
}
if let Some(key_fn) = key_fn {
let mut result_guard = HeapGuard::new(first_arg, vm);
{
let (result, vm) = result_guard.as_parts_mut();
let result_key = evaluate_key(result.clone_with_heap(vm), key_fn, key_context, vm)?;
let mut result_key_guard = HeapGuard::new(result_key, vm);
{
let (result_key, vm) = result_key_guard.as_parts_mut();
for item in positional {
defer_drop_mut!(item, vm);
let item_key = evaluate_key(item.clone_with_heap(vm), key_fn, key_context, vm)?;
defer_drop_mut!(item_key, vm);
if candidate_wins(result_key, item_key, is_min, vm)? {
std::mem::swap(result, item);
std::mem::swap(result_key, item_key);
}
}
}
let result_key = result_key_guard.into_inner();
result_key.drop_with_heap(vm);
}
Ok(result_guard.into_inner())
} else {
let mut result_guard = HeapGuard::new(first_arg, vm);
let (result, vm) = result_guard.as_parts_mut();
for item in positional {
defer_drop_mut!(item, vm);
if candidate_wins(result, item, is_min, vm)? {
std::mem::swap(result, item);
}
}
Ok(result_guard.into_inner())
}
}
}
/// Parses `key=` and `default=` for min()/max().
///
/// Returns `(key_fn, default_value)`. Passing `key=None` is normalized to `None`
/// so the comparison logic can treat it the same as omitting the keyword.
fn parse_min_max_kwargs(
kwargs: KwargsValues,
func_name: &str,
vm: &mut VM<'_, '_, impl ResourceTracker>,
) -> RunResult<(Option<Value>, Option<Value>)> {
let (key_fn, default_value) = kwargs.parse_named_kwargs_pair(
func_name,
"key",
"default",
vm.heap,
vm.interns,
ExcType::type_error_unexpected_keyword,
)?;
let key_fn = match key_fn {
Some(value) if matches!(value, Value::None) => {
value.drop_with_heap(vm);
None
}
other => other,
};
Ok((key_fn, default_value))
}
/// Calls the user-provided key function for a single candidate value.
///
/// The caller passes an owned clone of the candidate so this helper can forward it
/// into the function call without changing ownership of the original item being
/// tracked as the eventual min/max result.
fn evaluate_key(
item: Value,
key_fn: &Value,
key_context: &'static str,
vm: &mut VM<'_, '_, impl ResourceTracker>,
) -> RunResult<Value> {
vm.evaluate_function(key_context, key_fn, ArgValues::One(item))
}
/// Returns whether `candidate` should replace `current` as the best value seen so far.
///
/// `min()` replaces the current winner when the new candidate compares smaller,
/// while `max()` replaces it when the new candidate compares larger. Equal values
/// keep the existing winner so ties preserve the first-seen item, matching CPython.
fn candidate_wins(
current: &Value,
candidate: &Value,
is_min: bool,
vm: &mut VM<'_, '_, impl ResourceTracker>,
) -> RunResult<bool> {
let Some(ordering) = candidate.py_cmp(current, vm)? else {
return Err(ord_not_supported(candidate, current, is_min, vm.heap));
};
Ok((is_min && ordering == Ordering::Less) || (!is_min && ordering == Ordering::Greater))
}
/// Creates the CPython-compatible error for `default=` with multiple positional args.
#[cold]
fn default_with_multiple_args(func_name: &str) -> RunError {
SimpleException::new_msg(
ExcType::TypeError,
format!("Cannot specify a default for {func_name}() with multiple positional arguments"),
)
.into()
}
#[cold]
fn ord_not_supported(left: &Value, right: &Value, is_min: bool, heap: &Heap<impl ResourceTracker>) -> RunError {
let left_type = left.py_type(heap);
let right_type = right.py_type(heap);
let operator = if is_min { '<' } else { '>' };
ExcType::type_error(format!(
"'{operator}' not supported between instances of '{left_type}' and '{right_type}'"
))
}
================================================
FILE: crates/monty/src/builtins/mod.rs
================================================
//! Python builtin functions, types, and exception constructors.
//!
//! This module provides the interpreter-native implementation of Python builtins.
//! Each builtin function has its own submodule for organization.
mod abs;
mod all;
mod any;
mod bin;
mod chr;
mod divmod;
mod enumerate;
mod filter;
mod getattr;
mod hash;
mod hex;
mod id;
mod isinstance;
mod len;
mod map;
mod min_max; // min and max share implementation
mod next;
mod oct;
mod ord;
mod pow;
mod print;
mod repr;
mod reversed;
mod round;
mod sorted;
mod sum;
mod type_;
mod zip;
use std::{fmt::Write, str::FromStr};
use strum::{Display, EnumString, FromRepr, IntoStaticStr};
use crate::{
args::ArgValues,
bytecode::VM,
exception_private::{ExcType, RunResult},
resource::ResourceTracker,
types::Type,
value::Value,
};
/// Enumerates every interpreter-native Python builtins
///
/// Uses strum derives for automatic `Display`, `FromStr`, and `AsRef<str>` implementations.
/// All variants serialize to lowercase (e.g., `Print` -> "print").
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) enum Builtins {
/// A builtin function like `print`, `len`, `type`, etc.
Function(BuiltinsFunctions),
/// An exception type constructor like `ValueError`, `TypeError`, etc.
gitextract_527ed2df/
├── .cargo/
│ └── config.toml
├── .claude/
│ ├── settings.json
│ └── skills/
│ ├── coverage/
│ │ └── SKILL.md
│ ├── fastmod/
│ │ └── SKILL.md
│ └── python-playground/
│ └── SKILL.md
├── .codecov.yml
├── .github/
│ ├── actions/
│ │ └── build-pgo-wheel/
│ │ └── action.yml
│ └── workflows/
│ ├── ci.yml
│ ├── codspeed.yml
│ └── init-npm-packages.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .python-version
├── .rustfmt.toml
├── CLAUDE.md
├── Cargo.toml
├── LICENSE
├── Makefile
├── README.md
├── RELEASING.md
├── crates/
│ ├── fuzz/
│ │ ├── Cargo.toml
│ │ └── fuzz_targets/
│ │ ├── string_input_panic.rs
│ │ └── tokens_input_panic.rs
│ ├── monty/
│ │ ├── Cargo.toml
│ │ ├── benches/
│ │ │ └── main.rs
│ │ ├── build.rs
│ │ ├── src/
│ │ │ ├── args.rs
│ │ │ ├── asyncio.rs
│ │ │ ├── builtins/
│ │ │ │ ├── abs.rs
│ │ │ │ ├── all.rs
│ │ │ │ ├── any.rs
│ │ │ │ ├── bin.rs
│ │ │ │ ├── chr.rs
│ │ │ │ ├── divmod.rs
│ │ │ │ ├── enumerate.rs
│ │ │ │ ├── filter.rs
│ │ │ │ ├── getattr.rs
│ │ │ │ ├── hash.rs
│ │ │ │ ├── hex.rs
│ │ │ │ ├── id.rs
│ │ │ │ ├── isinstance.rs
│ │ │ │ ├── len.rs
│ │ │ │ ├── map.rs
│ │ │ │ ├── min_max.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── next.rs
│ │ │ │ ├── oct.rs
│ │ │ │ ├── ord.rs
│ │ │ │ ├── pow.rs
│ │ │ │ ├── print.rs
│ │ │ │ ├── repr.rs
│ │ │ │ ├── reversed.rs
│ │ │ │ ├── round.rs
│ │ │ │ ├── sorted.rs
│ │ │ │ ├── sum.rs
│ │ │ │ ├── type_.rs
│ │ │ │ └── zip.rs
│ │ │ ├── bytecode/
│ │ │ │ ├── builder.rs
│ │ │ │ ├── code.rs
│ │ │ │ ├── compiler.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── op.rs
│ │ │ │ └── vm/
│ │ │ │ ├── async_exec.rs
│ │ │ │ ├── attr.rs
│ │ │ │ ├── binary.rs
│ │ │ │ ├── call.rs
│ │ │ │ ├── collections.rs
│ │ │ │ ├── compare.rs
│ │ │ │ ├── exceptions.rs
│ │ │ │ ├── format.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── scheduler.rs
│ │ │ ├── exception_private.rs
│ │ │ ├── exception_public.rs
│ │ │ ├── expressions.rs
│ │ │ ├── fstring.rs
│ │ │ ├── function.rs
│ │ │ ├── heap.rs
│ │ │ ├── heap_data.rs
│ │ │ ├── heap_traits.rs
│ │ │ ├── intern.rs
│ │ │ ├── io.rs
│ │ │ ├── lib.rs
│ │ │ ├── modules/
│ │ │ │ ├── asyncio.rs
│ │ │ │ ├── math.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── os.rs
│ │ │ │ ├── pathlib.rs
│ │ │ │ ├── re.rs
│ │ │ │ ├── sys.rs
│ │ │ │ └── typing.rs
│ │ │ ├── namespace.rs
│ │ │ ├── object.rs
│ │ │ ├── os.rs
│ │ │ ├── parse.rs
│ │ │ ├── prepare.rs
│ │ │ ├── repl.rs
│ │ │ ├── resource.rs
│ │ │ ├── run.rs
│ │ │ ├── run_progress.rs
│ │ │ ├── signature.rs
│ │ │ ├── sorting.rs
│ │ │ ├── types/
│ │ │ │ ├── bytes.rs
│ │ │ │ ├── dataclass.rs
│ │ │ │ ├── dict.rs
│ │ │ │ ├── dict_view.rs
│ │ │ │ ├── iter.rs
│ │ │ │ ├── list.rs
│ │ │ │ ├── long_int.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── module.rs
│ │ │ │ ├── namedtuple.rs
│ │ │ │ ├── path.rs
│ │ │ │ ├── property.rs
│ │ │ │ ├── py_trait.rs
│ │ │ │ ├── range.rs
│ │ │ │ ├── re_match.rs
│ │ │ │ ├── re_pattern.rs
│ │ │ │ ├── set.rs
│ │ │ │ ├── slice.rs
│ │ │ │ ├── str.rs
│ │ │ │ ├── tuple.rs
│ │ │ │ └── type.rs
│ │ │ └── value.rs
│ │ ├── test_cases/
│ │ │ ├── args__dict_get_no_args.py
│ │ │ ├── args__dict_get_too_many.py
│ │ │ ├── args__dict_items_with_args.py
│ │ │ ├── args__dict_keys_with_args.py
│ │ │ ├── args__dict_pop_no_args.py
│ │ │ ├── args__dict_pop_too_many.py
│ │ │ ├── args__dict_values_with_args.py
│ │ │ ├── args__id_too_many.py
│ │ │ ├── args__len_no_args.py
│ │ │ ├── args__len_too_many.py
│ │ │ ├── args__len_type_error_int.py
│ │ │ ├── args__len_type_error_none.py
│ │ │ ├── args__list_append_no_args.py
│ │ │ ├── args__list_append_too_many.py
│ │ │ ├── args__list_insert_too_few.py
│ │ │ ├── args__list_insert_too_many.py
│ │ │ ├── args__repr_no_args.py
│ │ │ ├── arith__div_zero_float.py
│ │ │ ├── arith__div_zero_int.py
│ │ │ ├── arith__floordiv_zero_float.py
│ │ │ ├── arith__floordiv_zero_int.py
│ │ │ ├── arith__pow_zero_neg.py
│ │ │ ├── arith__pow_zero_neg_builtin.py
│ │ │ ├── assert__expr_fail.py
│ │ │ ├── assert__fail.py
│ │ │ ├── assert__fail_msg.py
│ │ │ ├── assert__fn_fail.py
│ │ │ ├── assert__ops.py
│ │ │ ├── async__asyncio_run.py
│ │ │ ├── async__basic.py
│ │ │ ├── async__closure.py
│ │ │ ├── async__double_await_coroutine.py
│ │ │ ├── async__exception.py
│ │ │ ├── async__ext_call.py
│ │ │ ├── async__gather_all.py
│ │ │ ├── async__nested_await.py
│ │ │ ├── async__nested_gather_ext.py
│ │ │ ├── async__not_awaitable.py
│ │ │ ├── async__not_imported.py
│ │ │ ├── async__recursion_depth_isolation.py
│ │ │ ├── async__return_types.py
│ │ │ ├── async__sequential.py
│ │ │ ├── async__traceback.py
│ │ │ ├── async__with_args.py
│ │ │ ├── attr__get_int_error.py
│ │ │ ├── attr__get_list_error.py
│ │ │ ├── attr__set_frozen_nonfield.py
│ │ │ ├── attr__set_int_error.py
│ │ │ ├── attr__set_list_error.py
│ │ │ ├── bench__kitchen_sink.py
│ │ │ ├── bool__ops.py
│ │ │ ├── builtin__add_type_error.py
│ │ │ ├── builtin__filter.py
│ │ │ ├── builtin__filter_not_iterable.py
│ │ │ ├── builtin__getattr.py
│ │ │ ├── builtin__iter_err_unpack_int.py
│ │ │ ├── builtin__iter_funcs.py
│ │ │ ├── builtin__iter_next.py
│ │ │ ├── builtin__map.py
│ │ │ ├── builtin__map_not_iterable.py
│ │ │ ├── builtin__math_funcs.py
│ │ │ ├── builtin__more_iter_funcs.py
│ │ │ ├── builtin__next_stop_iteration.py
│ │ │ ├── builtin__print_invalid_kwarg.py
│ │ │ ├── builtin__print_kwargs.py
│ │ │ ├── builtin__repr.py
│ │ │ ├── builtin__string_funcs.py
│ │ │ ├── bytes__decode_invalid_utf8.py
│ │ │ ├── bytes__endswith_str_error.py
│ │ │ ├── bytes__getitem_index_error.py
│ │ │ ├── bytes__index_start_gt_end.py
│ │ │ ├── bytes__methods.py
│ │ │ ├── bytes__negative_count.py
│ │ │ ├── bytes__ops.py
│ │ │ ├── bytes__startswith_str_error.py
│ │ │ ├── call_object.py
│ │ │ ├── chain_comparison__all.py
│ │ │ ├── closure__param_shadows_outer.py
│ │ │ ├── closure__pep448.py
│ │ │ ├── closure__undefined_nonlocal.py
│ │ │ ├── compare__mixed_types.py
│ │ │ ├── comprehension__all.py
│ │ │ ├── comprehension__scope.py
│ │ │ ├── comprehension__unbound_local.py
│ │ │ ├── dataclass__basic.py
│ │ │ ├── dataclass__call_field_error.py
│ │ │ ├── dataclass__frozen_set_error.py
│ │ │ ├── dataclass__get_missing_attr_error.py
│ │ │ ├── dict__get_unhashable_key.py
│ │ │ ├── dict__literal_unhashable_key.py
│ │ │ ├── dict__method_pop_missing_error.py
│ │ │ ├── dict__methods.py
│ │ │ ├── dict__ops.py
│ │ │ ├── dict__pop_unhashable_key.py
│ │ │ ├── dict__popitem_empty.py
│ │ │ ├── dict__subscript_missing_key.py
│ │ │ ├── dict__unhashable_dict_key.py
│ │ │ ├── dict__unhashable_list_key.py
│ │ │ ├── dict__unpack_type_error.py
│ │ │ ├── dict__views.py
│ │ │ ├── edge__all.py
│ │ │ ├── edge__float_int_mod.py
│ │ │ ├── edge__int_float_mod.py
│ │ │ ├── exc__args.py
│ │ │ ├── exc__str.py
│ │ │ ├── execute_ok__all.py
│ │ │ ├── execute_raise__error_instance_str.py
│ │ │ ├── execute_raise__error_no_args.py
│ │ │ ├── execute_raise__error_string_arg.py
│ │ │ ├── execute_raise__error_string_arg_quotes.py
│ │ │ ├── execute_raise__error_type.py
│ │ │ ├── execute_raise__raise_instance_via_var.py
│ │ │ ├── execute_raise__raise_list.py
│ │ │ ├── execute_raise__raise_number.py
│ │ │ ├── execute_raise__raise_type_call_via_var.py
│ │ │ ├── execute_raise__raise_type_direct.py
│ │ │ ├── execute_raise__raise_type_via_var.py
│ │ │ ├── ext_call__arg_side_effect_bug.py
│ │ │ ├── ext_call__augmented.py
│ │ │ ├── ext_call__augmented_refcount_bug.py
│ │ │ ├── ext_call__bare_raise_after_resume.py
│ │ │ ├── ext_call__basic.py
│ │ │ ├── ext_call__boolean.py
│ │ │ ├── ext_call__boolean_side_effect_hang.py
│ │ │ ├── ext_call__closure_bug.py
│ │ │ ├── ext_call__comparison.py
│ │ │ ├── ext_call__deep_call_stack.py
│ │ │ ├── ext_call__elif.py
│ │ │ ├── ext_call__exc.py
│ │ │ ├── ext_call__exc_deep_stack.py
│ │ │ ├── ext_call__exc_in_function.py
│ │ │ ├── ext_call__exc_nested_functions.py
│ │ │ ├── ext_call__ext_exc.py
│ │ │ ├── ext_call__for.py
│ │ │ ├── ext_call__fstring.py
│ │ │ ├── ext_call__if.py
│ │ │ ├── ext_call__if_condition.py
│ │ │ ├── ext_call__in_closure.py
│ │ │ ├── ext_call__in_function.py
│ │ │ ├── ext_call__in_function_simple.py
│ │ │ ├── ext_call__literals.py
│ │ │ ├── ext_call__multi_in_func.py
│ │ │ ├── ext_call__name_lookup.py
│ │ │ ├── ext_call__name_lookup_undefined.py
│ │ │ ├── ext_call__nested_calls.py
│ │ │ ├── ext_call__recursion_bug.py
│ │ │ ├── ext_call__return.py
│ │ │ ├── ext_call__side_effects.py
│ │ │ ├── ext_call__subscript.py
│ │ │ ├── ext_call__ternary.py
│ │ │ ├── ext_call__try.py
│ │ │ ├── ext_call__try_simple.py
│ │ │ ├── ext_call__unary.py
│ │ │ ├── frozenset__ops.py
│ │ │ ├── fstring__all.py
│ │ │ ├── fstring__error_eq_align_on_str.py
│ │ │ ├── fstring__error_float_f_on_str.py
│ │ │ ├── fstring__error_int_d_on_float.py
│ │ │ ├── fstring__error_int_d_on_str.py
│ │ │ ├── fstring__error_invalid_spec.py
│ │ │ ├── fstring__error_invalid_spec_dynamic.py
│ │ │ ├── fstring__error_invalid_spec_str.py
│ │ │ ├── fstring__error_str_s_on_int.py
│ │ │ ├── function__call_duplicate_kwargs.py
│ │ │ ├── function__call_unpack.py
│ │ │ ├── function__defaults.py
│ │ │ ├── function__err_duplicate_arg.py
│ │ │ ├── function__err_duplicate_first_arg.py
│ │ │ ├── function__err_duplicate_kwarg_cleanup.py
│ │ │ ├── function__err_kwonly_as_positional.py
│ │ │ ├── function__err_missing_all_posonly.py
│ │ │ ├── function__err_missing_heap_cleanup.py
│ │ │ ├── function__err_missing_kwonly.py
│ │ │ ├── function__err_missing_posonly_with_kwarg.py
│ │ │ ├── function__err_missing_with_posonly.py
│ │ │ ├── function__err_posonly_as_kwarg.py
│ │ │ ├── function__err_posonly_first_as_kwarg.py
│ │ │ ├── function__err_too_many_posonly.py
│ │ │ ├── function__err_too_many_with_kwonly.py
│ │ │ ├── function__err_unexpected_kwarg.py
│ │ │ ├── function__err_unexpected_kwarg_cleanup.py
│ │ │ ├── function__err_unexpected_kwarg_quote.py
│ │ │ ├── function__err_unexpected_kwarg_simple.py
│ │ │ ├── function__err_unpack_duplicate_arg.py
│ │ │ ├── function__err_unpack_duplicate_heap.py
│ │ │ ├── function__err_unpack_int.py
│ │ │ ├── function__err_unpack_nonstring_key.py
│ │ │ ├── function__err_unpack_not_mapping.py
│ │ │ ├── function__kwargs_unpacking.py
│ │ │ ├── function__ops.py
│ │ │ ├── function__return_none.py
│ │ │ ├── function__signatures.py
│ │ │ ├── function__too_few_args_all.py
│ │ │ ├── function__too_few_args_one.py
│ │ │ ├── function__too_few_args_two.py
│ │ │ ├── function__too_many_args_one.py
│ │ │ ├── function__too_many_args_two.py
│ │ │ ├── function__too_many_args_zero.py
│ │ │ ├── global__error_assigned_before.py
│ │ │ ├── global__ops.py
│ │ │ ├── hash__dict_unhashable.py
│ │ │ ├── hash__list_unhashable.py
│ │ │ ├── hash__ops.py
│ │ │ ├── id__bytes_literals_distinct.py
│ │ │ ├── id__int_copy_distinct.py
│ │ │ ├── id__is_number_is_number.py
│ │ │ ├── id__non_overlapping_lifetimes_distinct_types.py
│ │ │ ├── id__non_overlapping_lifetimes_same_types.py
│ │ │ ├── id__ops.py
│ │ │ ├── id__str_literals_same.py
│ │ │ ├── if__elif_else.py
│ │ │ ├── if__raise_elif.py
│ │ │ ├── if__raise_else.py
│ │ │ ├── if__raise_if.py
│ │ │ ├── if__raise_in_elif_condition.py
│ │ │ ├── if__raise_in_if_condition.py
│ │ │ ├── if_else_expr__all.py
│ │ │ ├── import__error_cannot_import.py
│ │ │ ├── import__error_module_not_found.py
│ │ │ ├── import__local_scope.py
│ │ │ ├── import__os.py
│ │ │ ├── import__relative_error.py
│ │ │ ├── import__relative_no_module_error.py
│ │ │ ├── import__runtime_error_when_executed.py
│ │ │ ├── import__star_error.py
│ │ │ ├── import__sys.py
│ │ │ ├── import__sys_monty.py
│ │ │ ├── import__type_checking_guard.py
│ │ │ ├── import__typing.py
│ │ │ ├── import__typing_type_ignore.py
│ │ │ ├── int__bigint.py
│ │ │ ├── int__bigint_errors.py
│ │ │ ├── int__ops.py
│ │ │ ├── int__overflow_division.py
│ │ │ ├── is_variant__all.py
│ │ │ ├── isinstance__arg2_list_error.py
│ │ │ ├── isinstance__arg2_type_error.py
│ │ │ ├── iter__dict_mutation.py
│ │ │ ├── iter__for.py
│ │ │ ├── iter__for_loop_unpacking.py
│ │ │ ├── iter__generator_expr.py
│ │ │ ├── iter__generator_expr_type.py
│ │ │ ├── iter__not_iterable.py
│ │ │ ├── lambda__all.py
│ │ │ ├── list__extend_not_iterable.py
│ │ │ ├── list__getitem_out_of_bounds.py
│ │ │ ├── list__index_not_found.py
│ │ │ ├── list__index_start_gt_end.py
│ │ │ ├── list__ops.py
│ │ │ ├── list__pop_empty.py
│ │ │ ├── list__pop_out_of_range.py
│ │ │ ├── list__pop_type_error.py
│ │ │ ├── list__remove_not_found.py
│ │ │ ├── list__setitem_dict_index.py
│ │ │ ├── list__setitem_huge_int_index.py
│ │ │ ├── list__setitem_index_error.py
│ │ │ ├── list__setitem_type_error.py
│ │ │ ├── list__unpack_type_error.py
│ │ │ ├── longint__index_error.py
│ │ │ ├── longint__repeat_error.py
│ │ │ ├── loop__break_continue.py
│ │ │ ├── loop__break_finally.py
│ │ │ ├── loop__break_in_function_error.py
│ │ │ ├── loop__break_in_if_error.py
│ │ │ ├── loop__break_nested_except_clears.py
│ │ │ ├── loop__break_outside_error.py
│ │ │ ├── loop__continue_finally.py
│ │ │ ├── loop__continue_in_function_error.py
│ │ │ ├── loop__continue_in_if_error.py
│ │ │ ├── loop__continue_nested_except_clears.py
│ │ │ ├── loop__continue_outside_error.py
│ │ │ ├── math__acos_domain_error.py
│ │ │ ├── math__acosh_domain_error.py
│ │ │ ├── math__asin_domain_error.py
│ │ │ ├── math__atanh_domain_error.py
│ │ │ ├── math__cos_inf_error.py
│ │ │ ├── math__cosh_overflow_error.py
│ │ │ ├── math__exp_overflow_error.py
│ │ │ ├── math__factorial_float_error.py
│ │ │ ├── math__factorial_negative_error.py
│ │ │ ├── math__floor_inf_error.py
│ │ │ ├── math__floor_nan_error.py
│ │ │ ├── math__floor_str_error.py
│ │ │ ├── math__fmod_inf_error.py
│ │ │ ├── math__gamma_neg_int_error.py
│ │ │ ├── math__gcd_float_error.py
│ │ │ ├── math__isqrt_negative_error.py
│ │ │ ├── math__ldexp_overflow_error.py
│ │ │ ├── math__log1p_domain_error.py
│ │ │ ├── math__log_base1_error.py
│ │ │ ├── math__log_zero_error.py
│ │ │ ├── math__module.py
│ │ │ ├── math__pow_domain_error.py
│ │ │ ├── math__sin_inf_error.py
│ │ │ ├── math__sqrt_negative_error.py
│ │ │ ├── math__tan_inf_error.py
│ │ │ ├── math__trunc_str_error.py
│ │ │ ├── method__args_kwargs_unpacking.py
│ │ │ ├── name_error__unbound_local_func.py
│ │ │ ├── name_error__unbound_local_module.py
│ │ │ ├── name_error__undefined_call_chained.py
│ │ │ ├── name_error__undefined_call_in_expr.py
│ │ │ ├── name_error__undefined_call_in_function.py
│ │ │ ├── name_error__undefined_call_with_args.py
│ │ │ ├── name_error__undefined_global.py
│ │ │ ├── namedtuple__missing_attr.py
│ │ │ ├── namedtuple__ops.py
│ │ │ ├── nonlocal__error_module_level.py
│ │ │ ├── nonlocal__ops.py
│ │ │ ├── os__environ.py
│ │ │ ├── os__getenv_key_list_error.py
│ │ │ ├── os__getenv_key_type_error.py
│ │ │ ├── parse_error__complex.py
│ │ │ ├── pathlib__import.py
│ │ │ ├── pathlib__os.py
│ │ │ ├── pathlib__os_read_error.py
│ │ │ ├── pathlib__pure.py
│ │ │ ├── pyobject__cycle_dict_self.py
│ │ │ ├── pyobject__cycle_list_dict.py
│ │ │ ├── pyobject__cycle_list_self.py
│ │ │ ├── pyobject__cycle_multiple_refs.py
│ │ │ ├── range__error_no_args.py
│ │ │ ├── range__error_step_zero.py
│ │ │ ├── range__error_too_many_args.py
│ │ │ ├── range__getitem_index_error.py
│ │ │ ├── range__ops.py
│ │ │ ├── re__basic.py
│ │ │ ├── re__grouping.py
│ │ │ ├── re__match.py
│ │ │ ├── recursion__deep_drop.py
│ │ │ ├── recursion__deep_eq.py
│ │ │ ├── recursion__deep_hash.py
│ │ │ ├── recursion__deep_repr.py
│ │ │ ├── recursion__function_depth.py
│ │ │ ├── refcount__cycle_mutual_reference.py
│ │ │ ├── refcount__cycle_self_reference.py
│ │ │ ├── refcount__dict_basic.py
│ │ │ ├── refcount__dict_get.py
│ │ │ ├── refcount__dict_keys_and.py
│ │ │ ├── refcount__dict_overwrite.py
│ │ │ ├── refcount__gather_cleanup.py
│ │ │ ├── refcount__gather_exception.py
│ │ │ ├── refcount__gather_nested_cancel.py
│ │ │ ├── refcount__immediate_skipped.py
│ │ │ ├── refcount__keyword_only_kwarg_arity_errors.py
│ │ │ ├── refcount__kwargs_unpacking.py
│ │ │ ├── refcount__list_append_multiple.py
│ │ │ ├── refcount__list_append_ref.py
│ │ │ ├── refcount__list_concat.py
│ │ │ ├── refcount__list_getitem.py
│ │ │ ├── refcount__list_iadd.py
│ │ │ ├── refcount__min_max_key_error_paths.py
│ │ │ ├── refcount__nested_list.py
│ │ │ ├── refcount__re_pattern_sub_error_paths.py
│ │ │ ├── refcount__re_search_match.py
│ │ │ ├── refcount__re_sub_error_paths.py
│ │ │ ├── refcount__shared_reference.py
│ │ │ ├── refcount__single_list.py
│ │ │ ├── repr__cycle_detection.py
│ │ │ ├── set__ops.py
│ │ │ ├── set__review_bugs.py
│ │ │ ├── set__unpack_type_error.py
│ │ │ ├── slice__invalid_indices.py
│ │ │ ├── slice__kwargs.py
│ │ │ ├── slice__no_args.py
│ │ │ ├── slice__ops.py
│ │ │ ├── slice__step_zero.py
│ │ │ ├── slice__step_zero_bytes.py
│ │ │ ├── slice__step_zero_range.py
│ │ │ ├── slice__step_zero_str.py
│ │ │ ├── slice__step_zero_tuple.py
│ │ │ ├── slice__too_many_args.py
│ │ │ ├── str__getitem_index_error.py
│ │ │ ├── str__index_not_found.py
│ │ │ ├── str__join_no_args.py
│ │ │ ├── str__join_non_string.py
│ │ │ ├── str__join_not_iterable.py
│ │ │ ├── str__join_too_many_args.py
│ │ │ ├── str__methods.py
│ │ │ ├── str__ops.py
│ │ │ ├── str__partition_empty.py
│ │ │ ├── str__rsplit_empty_sep.py
│ │ │ ├── str__split_empty_sep.py
│ │ │ ├── sys__types.py
│ │ │ ├── traceback__division_error.py
│ │ │ ├── traceback__index_error.py
│ │ │ ├── traceback__insert_as_int.py
│ │ │ ├── traceback__nested_call.py
│ │ │ ├── traceback__nonlocal_module_scope.py
│ │ │ ├── traceback__nonlocal_unbound.py
│ │ │ ├── traceback__range_as_int.py
│ │ │ ├── traceback__recursion_error.py
│ │ │ ├── traceback__set_mutation.py
│ │ │ ├── traceback__undefined_attr_call.py
│ │ │ ├── traceback__undefined_call.py
│ │ │ ├── traceback__undefined_raise.py
│ │ │ ├── try_except__all.py
│ │ │ ├── try_except__bare_raise_no_context.py
│ │ │ ├── try_except__invalid_type.py
│ │ │ ├── tuple__getitem_out_of_bounds.py
│ │ │ ├── tuple__index_not_found.py
│ │ │ ├── tuple__index_start_gt_end.py
│ │ │ ├── tuple__methods.py
│ │ │ ├── tuple__ops.py
│ │ │ ├── tuple__unpack_type_error.py
│ │ │ ├── type__builtin_attr_error.py
│ │ │ ├── type__bytes_negative.py
│ │ │ ├── type__cell_not_builtin.py
│ │ │ ├── type__exception_attr_error.py
│ │ │ ├── type__float_conversion_error.py
│ │ │ ├── type__float_repr_both_quotes.py
│ │ │ ├── type__float_repr_newline.py
│ │ │ ├── type__float_repr_single_quote.py
│ │ │ ├── type__int_conversion_error.py
│ │ │ ├── type__list_not_iterable.py
│ │ │ ├── type__non_builtin_name_error.py
│ │ │ ├── type__ops.py
│ │ │ ├── type__shadow_exc.py
│ │ │ ├── type__shadow_int.py
│ │ │ ├── type__shadow_len.py
│ │ │ ├── type__tuple_not_iterable.py
│ │ │ ├── type_error__int_add_list.py
│ │ │ ├── type_error__int_div_str.py
│ │ │ ├── type_error__int_floordiv_str.py
│ │ │ ├── type_error__int_iadd_str.py
│ │ │ ├── type_error__int_mod_str.py
│ │ │ ├── type_error__int_pow_str.py
│ │ │ ├── type_error__int_sub_str.py
│ │ │ ├── type_error__list_add_int.py
│ │ │ ├── type_error__list_add_str.py
│ │ │ ├── type_error__list_iadd_int.py
│ │ │ ├── type_error__str_add_int.py
│ │ │ ├── type_error__str_iadd_int.py
│ │ │ ├── type_error__unary_invert_str.py
│ │ │ ├── type_error__unary_minus_str.py
│ │ │ ├── type_error__unary_neg_str.py
│ │ │ ├── type_error__unary_plus_str.py
│ │ │ ├── typing__types.py
│ │ │ ├── unpack__nested.py
│ │ │ ├── unpack__non_sequence.py
│ │ │ ├── unpack__not_enough.py
│ │ │ ├── unpack__ops.py
│ │ │ ├── unpack__star_not_enough.py
│ │ │ ├── unpack__too_many.py
│ │ │ ├── version__cpython.py
│ │ │ ├── walrus__all.py
│ │ │ └── while__all.py
│ │ └── tests/
│ │ ├── asyncio.rs
│ │ ├── binary_serde.rs
│ │ ├── bytecode_limits.rs
│ │ ├── datatest_runner.rs
│ │ ├── inputs.rs
│ │ ├── json_serde.rs
│ │ ├── main.rs
│ │ ├── math_module.rs
│ │ ├── name_lookup.rs
│ │ ├── os_tests.rs
│ │ ├── parse_errors.rs
│ │ ├── print_writer.rs
│ │ ├── py_object.rs
│ │ ├── regex.rs
│ │ ├── repl.rs
│ │ ├── resource_limits.rs
│ │ └── try_from.rs
│ ├── monty-cli/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── monty-js/
│ │ ├── .cargo/
│ │ │ └── config.toml
│ │ ├── .gitignore
│ │ ├── .prettierignore
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── __test__/
│ │ │ ├── async.spec.ts
│ │ │ ├── basic.spec.ts
│ │ │ ├── exceptions.spec.ts
│ │ │ ├── external.spec.ts
│ │ │ ├── inputs.spec.ts
│ │ │ ├── limits.spec.ts
│ │ │ ├── package.json
│ │ │ ├── print.spec.ts
│ │ │ ├── repl.spec.ts
│ │ │ ├── serialize.spec.ts
│ │ │ ├── start.spec.ts
│ │ │ ├── type_check.spec.ts
│ │ │ └── types.spec.ts
│ │ ├── build.rs
│ │ ├── index-header.d.ts
│ │ ├── package.json
│ │ ├── scripts/
│ │ │ └── smoke-test.sh
│ │ ├── smoke-test/
│ │ │ ├── .gitignore
│ │ │ ├── package.json
│ │ │ ├── test.ts
│ │ │ └── tsconfig.json
│ │ ├── src/
│ │ │ ├── convert.rs
│ │ │ ├── exceptions.rs
│ │ │ ├── lib.rs
│ │ │ ├── limits.rs
│ │ │ └── monty_cls.rs
│ │ ├── tsconfig.json
│ │ └── wrapper.ts
│ ├── monty-python/
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── build.rs
│ │ ├── example.py
│ │ ├── exercise.py
│ │ ├── pyproject.toml
│ │ ├── python/
│ │ │ └── pydantic_monty/
│ │ │ ├── __init__.py
│ │ │ ├── _monty.pyi
│ │ │ ├── os_access.py
│ │ │ └── py.typed
│ │ ├── src/
│ │ │ ├── convert.rs
│ │ │ ├── dataclass.rs
│ │ │ ├── exceptions.rs
│ │ │ ├── external.rs
│ │ │ ├── lib.rs
│ │ │ ├── limits.rs
│ │ │ ├── monty_cls.rs
│ │ │ ├── repl.rs
│ │ │ └── serialization.rs
│ │ └── tests/
│ │ ├── test_async.py
│ │ ├── test_basic.py
│ │ ├── test_dataclasses.py
│ │ ├── test_exceptions.py
│ │ ├── test_external.py
│ │ ├── test_inputs.py
│ │ ├── test_limits.py
│ │ ├── test_os_access.py
│ │ ├── test_os_access_compat.py
│ │ ├── test_os_access_raw.py
│ │ ├── test_os_calls.py
│ │ ├── test_print.py
│ │ ├── test_re.py
│ │ ├── test_readme_examples.py
│ │ ├── test_repl.py
│ │ ├── test_serialize.py
│ │ ├── test_start.py
│ │ ├── test_threading.py
│ │ ├── test_type_check.py
│ │ └── test_types.py
│ ├── monty-type-checking/
│ │ ├── Cargo.toml
│ │ ├── src/
│ │ │ ├── db.rs
│ │ │ ├── lib.rs
│ │ │ └── type_check.rs
│ │ └── tests/
│ │ ├── bad_types.py
│ │ ├── bad_types_output.txt
│ │ ├── good_types.py
│ │ ├── main.rs
│ │ ├── reveal_types.py
│ │ └── reveal_types_output.txt
│ └── monty-typeshed/
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── README.md
│ ├── build.rs
│ ├── custom/
│ │ ├── README.md
│ │ ├── asyncio.pyi
│ │ ├── os.pyi
│ │ └── sys.pyi
│ ├── src/
│ │ └── lib.rs
│ ├── update.py
│ └── vendor/
│ └── typeshed/
│ ├── source_commit.txt
│ └── stdlib/
│ ├── VERSIONS
│ ├── _collections_abc.pyi
│ ├── _typeshed/
│ │ └── __init__.pyi
│ ├── asyncio.pyi
│ ├── builtins.pyi
│ ├── collections/
│ │ ├── __init__.pyi
│ │ └── abc.pyi
│ ├── dataclasses.pyi
│ ├── enum.pyi
│ ├── math.pyi
│ ├── os.pyi
│ ├── pathlib/
│ │ ├── __init__.pyi
│ │ └── types.pyi
│ ├── re.pyi
│ ├── sys.pyi
│ ├── types.pyi
│ ├── typing.pyi
│ └── typing_extensions.pyi
├── examples/
│ ├── README.md
│ ├── expense_analysis/
│ │ ├── README.md
│ │ ├── data.py
│ │ └── main.py
│ ├── sql_playground/
│ │ ├── README.md
│ │ ├── external_functions.py
│ │ ├── main.py
│ │ ├── sandbox_code.py
│ │ └── type_stubs.pyi
│ └── web_scraper/
│ ├── README.md
│ ├── browser.py
│ ├── example_code.py
│ ├── external_functions.py
│ ├── main.py
│ └── sub_agent.py
├── pyproject.toml
└── scripts/
├── check_imports.py
├── codecov_diff.py
├── complete_tests.py
├── flamegraph_to_text.py
├── iter_test_methods.py
├── run_traceback.py
└── startup_performance.py
Showing preview only (582K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (6669 symbols across 322 files)
FILE: crates/fuzz/fuzz_targets/string_input_panic.rs
function fuzz_limits (line 16) | fn fuzz_limits() -> LimitedTracker {
FILE: crates/fuzz/fuzz_targets/tokens_input_panic.rs
type Token (line 19) | enum Token {
type StringLit (line 64) | enum StringLit {
type ShortString (line 74) | enum ShortString {
type FloatLit (line 89) | enum FloatLit {
type VarName (line 101) | enum VarName {
type AttrName (line 128) | enum AttrName {
type BinOp (line 156) | enum BinOp {
type UnaryOp (line 176) | enum UnaryOp {
type CompareOp (line 185) | enum CompareOp {
type AugAssign (line 200) | enum AugAssign {
type Keyword (line 217) | enum Keyword {
type IndentLevel (line 245) | enum IndentLevel {
method fmt (line 254) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 291) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 303) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 320) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 334) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 363) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 393) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 415) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 426) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 443) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 462) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 492) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Tokens (line 508) | struct Tokens(Vec<Token>);
method arbitrary (line 511) | fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result...
method fmt (line 517) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method to_code (line 527) | fn to_code(&self) -> String {
function fuzz_limits (line 533) | fn fuzz_limits() -> LimitedTracker {
FILE: crates/monty-cli/src/main.rs
constant DIM (line 19) | const DIM: &str = "\x1b[2m";
constant BOLD_RED (line 21) | const BOLD_RED: &str = "\x1b[1m\x1b[31m";
constant BOLD_GREEN (line 23) | const BOLD_GREEN: &str = "\x1b[1m\x1b[32m";
constant BOLD_CYAN (line 25) | const BOLD_CYAN: &str = "\x1b[1m\x1b[36m";
constant RESET (line 27) | const RESET: &str = "\x1b[0m";
constant ARROW (line 28) | const ARROW: &str = "❯";
type Cli (line 39) | struct Cli {
method resource_limits (line 81) | fn resource_limits(&self) -> Option<ResourceLimits> {
constant EXT_FUNCTIONS (line 111) | const EXT_FUNCTIONS: bool = false;
function main (line 113) | fn main() -> ExitCode {
function dispatch_script (line 153) | fn dispatch_script(
function dispatch_repl (line 167) | fn dispatch_repl(file_path: &str, code: &str, limits: Option<ResourceLim...
function run_script (line 184) | fn run_script(file_path: &str, code: String, type_check_enabled: bool, t...
function run_repl (line 277) | fn run_repl(file_path: &str, code: &str, tracker: impl ResourceTracker) ...
function execute_repl_snippet (line 360) | fn execute_repl_snippet(repl: &mut MontyRepl<impl ResourceTracker>, snip...
function run_until_complete (line 381) | fn run_until_complete(mut progress: RunProgress<impl ResourceTracker>) -...
function resolve_external_call (line 427) | fn resolve_external_call(function_name: &str, args: &[MontyObject]) -> R...
function read_file (line 446) | fn read_file(file_path: &str) -> Result<String, String> {
type FormattedDuration (line 471) | struct FormattedDuration(Duration);
method fmt (line 474) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function sig_digits_after_decimal (line 500) | fn sig_digits_after_decimal(value: f64) -> usize {
function parse_memory_size (line 524) | fn parse_memory_size(s: &str) -> Result<usize, String> {
FILE: crates/monty-js/__test__/async.spec.ts
class ValueError (line 97) | class ValueError extends Error {
class ValueError (line 117) | class ValueError extends Error {
class ValueError (line 147) | class ValueError extends Error {
FILE: crates/monty-js/__test__/print.spec.ts
function makePrintCollector (line 9) | function makePrintCollector(t: ExecutionContext) {
function makeErrorCallback (line 104) | function makeErrorCallback(error: Error, t: ExecutionContext) {
FILE: crates/monty-js/__test__/start.spec.ts
function notFoobar (line 158) | function notFoobar(): unknown {
FILE: crates/monty-js/build.rs
function main (line 9) | fn main() {
function sync_package_json_version (line 20) | fn sync_package_json_version() {
FILE: crates/monty-js/index-header.d.ts
type JsMontyObject (line 3) | type JsMontyObject = any
FILE: crates/monty-js/smoke-test/test.ts
function assert (line 6) | function assert(condition: boolean, message: string): void {
function assertThrows (line 16) | function assertThrows<T extends Error>(fn: () => void, errorClass: new (...
FILE: crates/monty-js/src/convert.rs
constant JS_SAFE_INT_MIN (line 39) | const JS_SAFE_INT_MIN: i64 = -(1_i64 << 53);
constant JS_SAFE_INT_MAX (line 40) | const JS_SAFE_INT_MAX: i64 = 1_i64 << 53;
type JsMontyObject (line 45) | pub struct JsMontyObject<'env>(pub(crate) Unknown<'env>);
function raw (line 49) | pub fn raw(&self) -> sys::napi_value {
method to_napi_value (line 55) | unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::na...
function monty_to_js (line 71) | pub fn monty_to_js<'e>(obj: &MontyObject, env: &'e Env) -> Result<JsMont...
function create_js_null (line 107) | fn create_js_null(env: &Env) -> Result<Unknown<'_>> {
function create_js_bool (line 121) | fn create_js_bool(b: bool, env: &Env) -> Result<Unknown<'_>> {
function create_js_int (line 134) | fn create_js_int(i: i64, env: &Env) -> Result<Unknown<'_>> {
function create_js_bigint (line 147) | fn create_js_bigint<'e>(bi: &NumBigInt, env: &'e Env) -> Result<Unknown<...
function create_js_buffer (line 161) | fn create_js_buffer<'e>(bytes: &[u8], env: &'e Env) -> Result<Unknown<'e...
function create_js_array (line 167) | fn create_js_array<'e>(items: &[MontyObject], env: &'e Env) -> Result<Ar...
function create_js_tuple (line 180) | fn create_js_tuple<'e>(items: &[MontyObject], env: &'e Env) -> Result<Un...
function create_js_map (line 192) | fn create_js_map<'e>(pairs: &DictPairs, env: &'e Env) -> Result<Unknown<...
function call_method_2_args (line 211) | fn call_method_2_args(
function create_js_set (line 231) | fn create_js_set<'e>(items: &[MontyObject], env: &'e Env) -> Result<Unkn...
function create_js_ellipsis (line 245) | fn create_js_ellipsis(env: &Env) -> Result<Unknown<'_>> {
function create_js_exception (line 252) | fn create_js_exception<'e>(exc_type: ExcType, arg: Option<&str>, env: &'...
function create_js_type_marker (line 261) | fn create_js_type_marker<'e>(type_str: &str, env: &'e Env) -> Result<Unk...
function create_js_builtin_function_marker (line 269) | fn create_js_builtin_function_marker<'e>(func_str: &str, env: &'e Env) -...
function create_js_dataclass (line 277) | fn create_js_dataclass<'e>(
function js_to_monty (line 349) | pub fn js_to_monty(value: Unknown<'_>, env: Env) -> Result<MontyObject> {
function is_js_set (line 455) | fn is_js_set(obj: &Object, env: Env) -> Result<bool> {
function is_js_map (line 462) | fn is_js_map(obj: &Object, env: Env) -> Result<bool> {
function js_map_to_monty (line 469) | fn js_map_to_monty(map: Object, env: Env) -> Result<MontyObject> {
function js_set_to_monty (line 498) | fn js_set_to_monty(set: Object, env: Env) -> Result<MontyObject> {
function js_array_to_monty (line 521) | fn js_array_to_monty(arr: Object, env: Env) -> Result<MontyObject> {
function js_marked_object_to_monty (line 540) | fn js_marked_object_to_monty(obj: &Object, monty_type: &str, env: Env) -...
function js_object_to_monty_dict (line 617) | fn js_object_to_monty_dict(obj: Object, env: Env) -> Result<MontyObject> {
function get_string_property (line 635) | fn get_string_property(obj: &Object, name: &str) -> Result<Option<String...
FILE: crates/monty-js/src/exceptions.rs
type JsMontyException (line 35) | pub struct JsMontyException(monty::MontyException);
method fmt (line 38) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method exception (line 51) | pub fn exception(&self) -> ExceptionInfo {
method message (line 61) | pub fn message(&self) -> String {
method traceback (line 70) | pub fn traceback(&self) -> Vec<Frame> {
method display (line 81) | pub fn display(&self, format: Option<String>) -> Result<String> {
method to_js_string (line 104) | pub fn to_js_string(&self) -> String {
method new (line 112) | pub fn new(exc: monty::MontyException) -> Self {
type MontyTypingError (line 126) | pub struct MontyTypingError {
method fmt (line 134) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method exception (line 144) | pub fn exception(&self) -> ExceptionInfo {
method message (line 154) | pub fn message(&self) -> String {
method display (line 172) | pub fn display(&self, format: Option<String>, color: Option<bool>) -> ...
method to_js_string (line 187) | pub fn to_js_string(&self) -> String {
method from_failure (line 195) | pub fn from_failure(failure: TypeCheckingDiagnostics) -> Self {
type ExceptionInfo (line 211) | pub struct ExceptionInfo {
type Frame (line 224) | pub struct Frame {
method from_stack_frame (line 244) | pub fn from_stack_frame(frame: &StackFrame) -> Self {
function exc_js_to_monty (line 258) | pub fn exc_js_to_monty(js_err: napi::Error) -> ::monty::MontyException {
function js_err_to_exc_type (line 265) | fn js_err_to_exc_type(exc: napi::Status) -> ::monty::ExcType {
FILE: crates/monty-js/src/limits.rs
type JsResourceLimits (line 16) | pub struct JsResourceLimits {
method from (line 30) | fn from(js_limits: JsResourceLimits) -> Self {
FILE: crates/monty-js/src/monty_cls.rs
type Monty (line 73) | pub struct Monty {
method create (line 133) | pub fn create(
method type_check (line 171) | pub fn type_check(&self, prefix_code: Option<String>) -> Result<Option...
method run (line 184) | pub fn run<'env>(
method run_with_external_functions (line 234) | fn run_with_external_functions<'env>(
method start (line 314) | pub fn start<'env>(
method dump (line 361) | pub fn dump(&self) -> Result<Buffer> {
method load (line 377) | pub fn load(data: Buffer) -> Result<Self> {
method script_name (line 390) | pub fn script_name(&self) -> String {
method inputs (line 396) | pub fn inputs(&self) -> Vec<String> {
method repr (line 402) | pub fn repr(&self) -> String {
method extract_input_values (line 419) | fn extract_input_values(&self, inputs: Option<Object<'_>>, env: Env) -...
type MontyOptions (line 85) | pub struct MontyOptions {
type RunOptions (line 99) | pub struct RunOptions<'env> {
type StartOptions (line 113) | pub struct StartOptions<'env> {
function run_type_check_result (line 427) | fn run_type_check_result(code: &str, script_name: &str, prefix_code: Opt...
type EitherRepl (line 450) | enum EitherRepl {
type MontyReplOptions (line 461) | pub struct MontyReplOptions {
type MontyRepl (line 473) | pub struct MontyRepl {
method new (line 488) | pub fn new(options: Option<MontyReplOptions>) -> Self {
method script_name (line 505) | pub fn script_name(&self) -> String {
method feed (line 511) | pub fn feed<'env>(
method dump (line 529) | pub fn dump(&self) -> Result<Buffer> {
method load (line 541) | pub fn load(data: Buffer) -> Result<Self> {
method repr (line 553) | pub fn repr(&self) -> String {
type ResolvedMontyOptions (line 562) | struct ResolvedMontyOptions {
function resolve_monty_options (line 570) | fn resolve_monty_options(options: Option<MontyOptions>) -> ResolvedMonty...
function extract_input_values_in_order (line 590) | fn extract_input_values_in_order(
type EitherSnapshot (line 630) | enum EitherSnapshot {
method from_snapshot (line 1186) | fn from_snapshot(call: FunctionCall<NoLimitTracker>) -> Self {
method from_snapshot (line 1192) | fn from_snapshot(call: FunctionCall<LimitedTracker>) -> Self {
type MontySnapshot (line 646) | pub struct MontySnapshot {
method script_name (line 692) | pub fn script_name(&self) -> String {
method function_name (line 698) | pub fn function_name(&self) -> String {
method args (line 704) | pub fn args<'env>(&self, env: &'env Env) -> Result<Vec<JsMontyObject<'...
method kwargs (line 710) | pub fn kwargs<'env>(&self, env: &'env Env) -> Result<Object<'env>> {
method resume (line 732) | pub fn resume<'env>(
method dump (line 802) | pub fn dump(&self) -> Result<Buffer> {
method load (line 826) | pub fn load(data: Buffer, options: Option<SnapshotLoadOptions>) -> Res...
method repr (line 846) | pub fn repr(&self) -> String {
type ResumeOptions (line 663) | pub struct ResumeOptions<'env> {
type ExceptionInput (line 673) | pub struct ExceptionInput {
type SnapshotLoadOptions (line 682) | pub struct SnapshotLoadOptions<'env> {
type MontyComplete (line 862) | pub struct MontyComplete {
method output (line 871) | pub fn output<'env>(&self, env: &'env Env) -> Result<JsMontyObject<'en...
method repr (line 878) | pub fn repr(&self) -> String {
type EitherLookupSnapshot (line 892) | enum EitherLookupSnapshot {
method from_lookup (line 906) | fn from_lookup(lookup: NameLookup<NoLimitTracker>) -> Self {
method from_lookup (line 912) | fn from_lookup(lookup: NameLookup<LimitedTracker>) -> Self {
type FromLookupSnapshot (line 900) | trait FromLookupSnapshot<T: ResourceTracker> {
method from_lookup (line 902) | fn from_lookup(lookup: NameLookup<T>) -> Self;
type MontyNameLookup (line 927) | pub struct MontyNameLookup {
method script_name (line 959) | pub fn script_name(&self) -> String {
method variable_name (line 965) | pub fn variable_name(&self) -> String {
method resume (line 978) | pub fn resume<'env>(
method dump (line 1032) | pub fn dump(&self) -> Result<Buffer> {
method load (line 1056) | pub fn load(data: Buffer, options: Option<NameLookupLoadOptions>) -> R...
method repr (line 1074) | pub fn repr(&self) -> String {
type NameLookupResumeOptions (line 943) | pub struct NameLookupResumeOptions<'env> {
type NameLookupLoadOptions (line 950) | pub struct NameLookupLoadOptions<'env> {
type JsPrintCallback (line 1083) | type JsPrintCallback<'env> = Function<'env, FnArgs<(&'static str, String...
type JsPrintCallbackRef (line 1084) | type JsPrintCallbackRef = FunctionRef<FnArgs<(&'static str, String)>, ()>;
type CallbackStringPrint (line 1089) | pub struct CallbackStringPrint<'env>(JsPrintCallback<'env>);
function new_js (line 1093) | pub fn new_js(env: &'env Env, func: &JsPrintCallback<'env>) -> napi::Res...
function new_js_ref (line 1100) | pub fn new_js_ref(env: &'env Env, func: &JsPrintCallbackRef) -> napi::Re...
method stdout_write (line 1106) | fn stdout_write(&mut self, output: Cow<'_, str>) -> std::result::Result<...
method stdout_push (line 1113) | fn stdout_push(&mut self, end: char) -> std::result::Result<(), MontyExc...
function progress_to_result (line 1134) | fn progress_to_result<T>(
type FromSnapshot (line 1180) | trait FromSnapshot<T: ResourceTracker> {
method from_snapshot (line 1182) | fn from_snapshot(call: FunctionCall<T>) -> Self;
function string_to_exc_type (line 1198) | fn string_to_exc_type(type_name: &str) -> Result<ExcType> {
type SerializedMonty (line 1210) | struct SerializedMonty {
type SerializedRepl (line 1218) | struct SerializedRepl<'a> {
type SerializedReplOwned (line 1225) | struct SerializedReplOwned {
type SerializedSnapshot (line 1232) | struct SerializedSnapshot<'a> {
type SerializedSnapshotOwned (line 1242) | struct SerializedSnapshotOwned {
type SerializedNameLookup (line 1252) | struct SerializedNameLookup<'a> {
type SerializedNameLookupOwned (line 1260) | struct SerializedNameLookupOwned {
function call_external_function (line 1274) | fn call_external_function(
function extract_js_exception (line 1377) | fn extract_js_exception(exception_obj: Object<'_>) -> MontyException {
function resolve_name_lookup (line 1397) | fn resolve_name_lookup(external_functions: Option<&Object<'_>>, name: &s...
FILE: crates/monty-js/wrapper.ts
type JsResourceLimits (line 47) | type JsResourceLimits = ResourceLimits
class MontyError (line 55) | class MontyError extends Error {
method constructor (line 59) | constructor(typeName: string, message: string) {
method exception (line 73) | get exception(): ExceptionInfo {
method display (line 84) | display(format: 'type-msg' | 'msg' = 'msg'): string {
class MontySyntaxError (line 102) | class MontySyntaxError extends MontyError {
method constructor (line 105) | constructor(messageOrNative: string | NativeMontyException) {
method display (line 124) | override display(format: 'type-msg' | 'msg' = 'msg'): string {
class MontyRuntimeError (line 138) | class MontyRuntimeError extends MontyError {
method constructor (line 143) | constructor(
method traceback (line 172) | traceback(): Frame[] {
method display (line 183) | display(format: 'traceback' | 'type-msg' | 'msg' = 'traceback'): string {
type TypingDisplayFormat (line 201) | type TypingDisplayFormat =
class MontyTypingError (line 219) | class MontyTypingError extends MontyError {
method constructor (line 222) | constructor(messageOrNative: string | NativeMontyTypingError, nativeEr...
method displayDiagnostics (line 243) | displayDiagnostics(format: TypingDisplayFormat = 'full', color: boolea...
class Monty (line 254) | class Monty {
method constructor (line 265) | constructor(code: string, options?: MontyOptions) {
method typeCheck (line 288) | typeCheck(prefixCode?: string): void {
method run (line 302) | run(options?: RunOptions): JsMontyObject {
method start (line 318) | start(options?: StartOptions): MontySnapshot | MontyNameLookup | Monty...
method dump (line 326) | dump(): Buffer {
method load (line 333) | static load(data: Buffer): Monty {
method scriptName (line 340) | get scriptName(): string {
method inputs (line 345) | get inputs(): string[] {
method repr (line 350) | repr(): string {
type MontyReplOptions (line 356) | interface MontyReplOptions {
class MontyRepl (line 369) | class MontyRepl {
method constructor (line 377) | constructor(options?: MontyReplOptions) {
method scriptName (line 382) | get scriptName(): string {
method feed (line 393) | feed(code: string): JsMontyObject {
method dump (line 402) | dump(): Buffer {
method load (line 407) | static load(data: Buffer): MontyRepl {
method repr (line 415) | repr(): string {
function wrapStartResult (line 423) | function wrapStartResult(
class MontySnapshot (line 449) | class MontySnapshot {
method constructor (line 452) | constructor(nativeSnapshot: NativeMontySnapshot) {
method scriptName (line 457) | get scriptName(): string {
method functionName (line 462) | get functionName(): string {
method args (line 467) | get args(): JsMontyObject[] {
method kwargs (line 472) | get kwargs(): Record<string, JsMontyObject> {
method resume (line 484) | resume(options: ResumeOptions): MontySnapshot | MontyNameLookup | Mont...
method dump (line 492) | dump(): Buffer {
method load (line 499) | static load(data: Buffer, options?: SnapshotLoadOptions): MontySnapshot {
method repr (line 505) | repr(): string {
class MontyNameLookup (line 517) | class MontyNameLookup {
method constructor (line 520) | constructor(nativeNameLookup: NativeMontyNameLookup) {
method scriptName (line 525) | get scriptName(): string {
method variableName (line 530) | get variableName(): string {
method resume (line 545) | resume(options?: NameLookupResumeOptions): MontySnapshot | MontyNameLo...
method dump (line 553) | dump(): Buffer {
method load (line 560) | static load(data: Buffer, options?: NameLookupLoadOptions): MontyNameL...
method repr (line 566) | repr(): string {
class MontyComplete (line 574) | class MontyComplete {
method constructor (line 577) | constructor(nativeComplete: NativeMontyComplete) {
method output (line 582) | get output(): JsMontyObject {
method repr (line 587) | repr(): string {
type RunMontyAsyncOptions (line 595) | interface RunMontyAsyncOptions {
function runMontyAsync (line 634) | async function runMontyAsync(montyRunner: Monty, options: RunMontyAsyncO...
FILE: crates/monty-python/build.rs
function main (line 1) | fn main() {
FILE: crates/monty-python/example.py
function fetch (line 25) | def fetch(url: str) -> str:
FILE: crates/monty-python/exercise.py
function main (line 14) | def main():
FILE: crates/monty-python/python/pydantic_monty/__init__.py
function run_monty_async (line 60) | async def run_monty_async(
function run_repl_async (line 93) | async def run_repl_async(
function _run_in_pool (line 125) | async def _run_in_pool(func: Callable[[], T]) -> T:
function _dispatch_loop (line 135) | async def _dispatch_loop(
function _run_external_function (line 237) | async def _run_external_function(call_id: int, coro: Awaitable[Any]) -> ...
class ResourceLimits (line 246) | class ResourceLimits(TypedDict, total=False):
class ExternalReturnValue (line 269) | class ExternalReturnValue(TypedDict):
class ExternalException (line 273) | class ExternalException(TypedDict):
class ExternalFuture (line 277) | class ExternalFuture(TypedDict):
FILE: crates/monty-python/python/pydantic_monty/_monty.pyi
class Monty (line 28) | class Monty:
method __new__ (line 37) | def __new__(
method type_check (line 65) | def type_check(self, prefix_code: str | None = None) -> None:
method run (line 82) | def run(
method start (line 113) | def start(
method dump (line 142) | def dump(self) -> bytes:
method load (line 157) | def load(
method register_dataclass (line 177) | def register_dataclass(self, cls: type) -> None:
method __repr__ (line 192) | def __repr__(self) -> str: ...
class MontyRepl (line 195) | class MontyRepl:
method __new__ (line 203) | def __new__(
method script_name (line 217) | def script_name(self) -> str:
method register_dataclass (line 220) | def register_dataclass(self, cls: type) -> None:
method feed_run (line 225) | def feed_run(
method feed_start (line 245) | def feed_start(
method dump (line 267) | def dump(self) -> bytes:
method load (line 271) | def load(
class FunctionSnapshot (line 279) | class FunctionSnapshot:
method script_name (line 288) | def script_name(self) -> str:
method is_os_function (line 292) | def is_os_function(self) -> bool:
method is_method_call (line 296) | def is_method_call(self) -> bool:
method function_name (line 300) | def function_name(self) -> str | OsFunction:
method args (line 307) | def args(self) -> tuple[Any, ...]:
method kwargs (line 311) | def kwargs(self) -> dict[str, Any]:
method call_id (line 315) | def call_id(self) -> int:
method resume (line 319) | def resume(self, *, return_value: Any) -> FunctionSnapshot | NameLooku...
method resume (line 344) | def resume(
method resume (line 353) | def resume(self, *, future: EllipsisType) -> FunctionSnapshot | NameLo...
method dump (line 361) | def dump(self) -> bytes:
method __repr__ (line 379) | def __repr__(self) -> str: ...
class NameLookupSnapshot (line 382) | class NameLookupSnapshot:
method script_name (line 391) | def script_name(self) -> str:
method variable_name (line 395) | def variable_name(self) -> str:
method resume (line 398) | def resume(
method dump (line 426) | def dump(self) -> bytes:
method __repr__ (line 444) | def __repr__(self) -> str: ...
class FutureSnapshot (line 447) | class FutureSnapshot:
method script_name (line 456) | def script_name(self) -> str:
method pending_call_ids (line 460) | def pending_call_ids(self) -> list[int]:
method resume (line 466) | def resume(
method dump (line 492) | def dump(self) -> bytes:
method __repr__ (line 510) | def __repr__(self) -> str: ...
class MontyComplete (line 513) | class MontyComplete:
method output (line 517) | def output(self) -> Any:
method __repr__ (line 520) | def __repr__(self) -> str: ...
class MontyError (line 522) | class MontyError(Exception):
method exception (line 529) | def exception(self) -> BaseException:
method __str__ (line 532) | def __str__(self) -> str:
class MontySyntaxError (line 536) | class MontySyntaxError(MontyError):
method display (line 542) | def display(self, format: Literal['type-msg', 'msg'] = 'msg') -> str:
class MontyTypingError (line 551) | class MontyTypingError(MontyError):
method display (line 562) | def display(
class MontyRuntimeError (line 577) | class MontyRuntimeError(MontyError):
method traceback (line 584) | def traceback(self) -> list[Frame]:
method display (line 587) | def display(self, format: Literal['traceback', 'type-msg', 'msg'] = 't...
class Frame (line 597) | class Frame:
method filename (line 601) | def filename(self) -> str:
method line (line 605) | def line(self) -> int:
method column (line 609) | def column(self) -> int:
method end_line (line 613) | def end_line(self) -> int:
method end_column (line 617) | def end_column(self) -> int:
method function_name (line 621) | def function_name(self) -> str | None:
method source_line (line 625) | def source_line(self) -> str | None:
method dict (line 628) | def dict(self) -> dict[str, int | str | None]:
function load_snapshot (line 631) | def load_snapshot(
function load_repl_snapshot (line 655) | def load_repl_snapshot(
FILE: crates/monty-python/python/pydantic_monty/os_access.py
class StatResult (line 35) | class StatResult(NamedTuple):
method file_stat (line 39) | def file_stat(cls, size: int, mode: int = 0o644, mtime: float | None =...
method dir_stat (line 59) | def dir_stat(cls, mode: int = 0o755, mtime: float | None = None) -> Self:
class AbstractOS (line 111) | class AbstractOS(ABC):
method __call__ (line 120) | def __call__(self, function_name: OsFunction, args: tuple[Any, ...], k...
method path_exists (line 177) | def path_exists(self, path: PurePosixPath) -> bool:
method path_is_file (line 189) | def path_is_file(self, path: PurePosixPath) -> bool:
method path_is_dir (line 201) | def path_is_dir(self, path: PurePosixPath) -> bool:
method path_is_symlink (line 213) | def path_is_symlink(self, path: PurePosixPath) -> bool:
method path_read_text (line 225) | def path_read_text(self, path: PurePosixPath) -> str:
method path_read_bytes (line 241) | def path_read_bytes(self, path: PurePosixPath) -> bytes:
method path_write_text (line 257) | def path_write_text(self, path: PurePosixPath, data: str) -> int:
method path_write_bytes (line 274) | def path_write_bytes(self, path: PurePosixPath, data: bytes) -> int:
method path_mkdir (line 291) | def path_mkdir(self, path: PurePosixPath, parents: bool, exist_ok: boo...
method path_unlink (line 306) | def path_unlink(self, path: PurePosixPath) -> None:
method path_rmdir (line 319) | def path_rmdir(self, path: PurePosixPath) -> None:
method path_iterdir (line 333) | def path_iterdir(self, path: PurePosixPath) -> list[PurePosixPath]:
method path_stat (line 349) | def path_stat(self, path: PurePosixPath) -> StatResult:
method path_rename (line 366) | def path_rename(self, path: PurePosixPath, target: PurePosixPath) -> N...
method path_resolve (line 380) | def path_resolve(self, path: PurePosixPath) -> str:
method path_absolute (line 392) | def path_absolute(self, path: PurePosixPath) -> str:
method getenv (line 404) | def getenv(self, key: str, default: str | None = None) -> str | None:
method get_environ (line 417) | def get_environ(self) -> dict[str, str]:
class AbstractFile (line 426) | class AbstractFile(Protocol):
method read_content (line 455) | def read_content(self) -> str | bytes:
method write_content (line 459) | def write_content(self, content: str | bytes) -> None:
method delete (line 463) | def delete(self) -> None:
function _is_file (line 471) | def _is_file(entry: None | AbstractFile | Tree) -> TypeGuard[AbstractFile]:
function _is_dir (line 475) | def _is_dir(entry: None | AbstractFile | Tree) -> TypeGuard[Tree]:
class MemoryFile (line 479) | class MemoryFile:
method __init__ (line 519) | def __init__(self, path: str | PurePosixPath, content: str | bytes, *,...
method read_content (line 533) | def read_content(self) -> str | bytes:
method write_content (line 537) | def write_content(self, content: str | bytes) -> None:
method delete (line 541) | def delete(self) -> None:
method __repr__ (line 545) | def __repr__(self) -> str:
class CallbackFile (line 553) | class CallbackFile:
method __init__ (line 601) | def __init__(
method read_content (line 624) | def read_content(self) -> str | bytes:
method write_content (line 628) | def write_content(self, content: str | bytes) -> None:
method delete (line 632) | def delete(self) -> None:
method __repr__ (line 636) | def __repr__(self) -> str:
class OSAccess (line 643) | class OSAccess(AbstractOS):
method __init__ (line 670) | def __init__(
method __repr__ (line 714) | def __repr__(self) -> str:
method path_exists (line 717) | def path_exists(self, path: PurePosixPath) -> bool:
method path_is_file (line 720) | def path_is_file(self, path: PurePosixPath) -> bool:
method path_is_dir (line 723) | def path_is_dir(self, path: PurePosixPath) -> bool:
method path_is_symlink (line 726) | def path_is_symlink(self, path: PurePosixPath) -> bool:
method path_read_text (line 729) | def path_read_text(self, path: PurePosixPath) -> str:
method path_read_bytes (line 734) | def path_read_bytes(self, path: PurePosixPath) -> bytes:
method path_write_text (line 739) | def path_write_text(self, path: PurePosixPath, data: str) -> int:
method path_write_bytes (line 743) | def path_write_bytes(self, path: PurePosixPath, data: bytes) -> int:
method _write_file (line 747) | def _write_file(self, path: PurePosixPath, data: bytes | str) -> None:
method path_mkdir (line 764) | def path_mkdir(self, path: PurePosixPath, parents: bool, exist_ok: boo...
method path_unlink (line 791) | def path_unlink(self, path: PurePosixPath) -> None:
method path_rmdir (line 799) | def path_rmdir(self, path: PurePosixPath) -> None:
method path_iterdir (line 808) | def path_iterdir(self, path: PurePosixPath) -> list[PurePosixPath]:
method path_stat (line 813) | def path_stat(self, path: PurePosixPath) -> StatResult:
method path_rename (line 822) | def path_rename(self, path: PurePosixPath, target: PurePosixPath) -> N...
method path_resolve (line 865) | def path_resolve(self, path: PurePosixPath) -> str:
method path_absolute (line 869) | def path_absolute(self, path: PurePosixPath) -> str:
method getenv (line 876) | def getenv(self, key: str, default: str | None = None) -> str | None:
method get_environ (line 879) | def get_environ(self) -> dict[str, str]:
method _get_entry (line 882) | def _get_entry(self, path: PurePosixPath) -> Tree | AbstractFile | None:
method _get_entry_exists (line 896) | def _get_entry_exists(self, path: PurePosixPath) -> Tree | AbstractFile:
method _get_file (line 903) | def _get_file(self, path: PurePosixPath) -> AbstractFile:
method _get_dir (line 910) | def _get_dir(self, path: PurePosixPath) -> Tree:
method _parent_entry (line 917) | def _parent_entry(self, path: PurePosixPath) -> Tree | AbstractFile | ...
method _update_paths_recursive (line 920) | def _update_paths_recursive(self, tree: Tree, old_prefix: PurePosixPat...
FILE: crates/monty-python/src/convert.rs
function py_to_monty (line 35) | pub fn py_to_monty(obj: &Bound<'_, PyAny>, dc_registry: &DcRegistry) -> ...
function monty_to_py (line 138) | pub fn monty_to_py(py: Python<'_>, obj: &MontyObject, dc_registry: &DcRe...
function import_builtins (line 242) | pub fn import_builtins(py: Python<'_>) -> PyResult<&Py<PyModule>> {
function get_namedtuple (line 249) | fn get_namedtuple(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>> {
function get_pure_posix_path (line 256) | fn get_pure_posix_path(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>> {
function get_name (line 262) | pub fn get_name(f: &Bound<'_, PyAny>) -> String {
function get_docstring (line 269) | pub fn get_docstring(f: &Bound<'_, PyAny>) -> Option<String> {
FILE: crates/monty-python/src/dataclass.rs
function is_dataclass (line 28) | pub fn is_dataclass(value: &Bound<'_, PyAny>) -> bool {
function dataclass_to_monty (line 41) | pub fn dataclass_to_monty(value: &Bound<'_, PyAny>, dc_registry: &DcRegi...
function dataclass_to_py (line 98) | pub fn dataclass_to_py(
type DcRegistry (line 143) | pub struct DcRegistry {
method new (line 149) | pub fn new(py: Python<'_>) -> Self {
method from_list (line 159) | pub fn from_list(py: Python<'_>, dataclass_registry: Option<&Bound<'_,...
method clone_ref (line 174) | pub fn clone_ref(&self, py: Python<'_>) -> Self {
method insert (line 187) | pub fn insert<T>(&self, obj: &Bound<'_, T>) -> PyResult<()> {
method get (line 194) | pub fn get(&self, py: Python<'_>, type_id: u64) -> PyResult<Option<Py<...
type PyUnknownDataclass (line 208) | pub struct PyUnknownDataclass {
method __dataclass_fields__ (line 226) | fn __dataclass_fields__(&self, py: Python<'_>) -> PyResult<Py<PyDict>> {
method __dataclass_params__ (line 286) | fn __dataclass_params__(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
method __getattr__ (line 319) | fn __getattr__(&self, py: Python<'_>, name: &str) -> PyResult<Py<PyAny...
method __setattr__ (line 332) | fn __setattr__(&self, py: Python<'_>, name: &str, value: Py<PyAny>) ->...
method __repr__ (line 344) | fn __repr__(&self, py: Python<'_>) -> PyResult<String> {
method __eq__ (line 357) | fn __eq__(&self, py: Python<'_>, other: &Bound<'_, PyAny>) -> PyResult...
method __hash__ (line 373) | fn __hash__(&self, py: Python<'_>) -> PyResult<isize> {
method new (line 404) | pub fn new<'a>(
function get_field_marker (line 429) | fn get_field_marker(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>> {
function get_missing (line 436) | fn get_missing(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>> {
function get_field_class (line 443) | fn get_field_class(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>> {
function get_dataclass_params_class (line 450) | fn get_dataclass_params_class(py: Python<'_>) -> PyResult<&Bound<'_, PyA...
function get_frozen_instance_error (line 457) | pub fn get_frozen_instance_error(py: Python<'_>) -> PyResult<&Bound<'_, ...
FILE: crates/monty-python/src/exceptions.rs
type MontyError (line 34) | pub struct MontyError {
method new_err (line 46) | pub fn new_err(py: Python<'_>, exc: MontyException) -> PyErr {
method new (line 59) | pub fn new(exc: MontyException) -> Self {
method exc_type (line 64) | fn exc_type(&self) -> ExcType {
method message (line 69) | fn message(&self) -> Option<&str> {
method exception (line 80) | fn exception(&self, py: Python<'_>) -> Py<PyAny> {
method __str__ (line 85) | fn __str__(&self) -> String {
method __repr__ (line 89) | fn __repr__(&self) -> String {
type MontySyntaxError (line 104) | pub struct MontySyntaxError;
method new_err (line 109) | pub fn new_err(py: Python<'_>, exc: MontyException) -> PyErr {
method display (line 128) | fn display(slf: PyRef<'_, Self>, format: &str) -> PyResult<String> {
method __str__ (line 140) | fn __str__(slf: PyRef<'_, Self>) -> String {
method __repr__ (line 145) | fn __repr__(slf: PyRef<'_, Self>) -> String {
type MontyTypingError (line 161) | pub struct MontyTypingError {
method new_err (line 168) | pub fn new_err(py: Python<'_>, failure: TypeCheckingDiagnostics) -> Py...
method display (line 187) | fn display(&self, format: &str, color: bool) -> PyResult<String> {
method __str__ (line 196) | fn __str__(&self) -> String {
method __repr__ (line 200) | fn __repr__(&self) -> String {
type MontyRuntimeError (line 210) | pub struct MontyRuntimeError {
method new_err (line 218) | pub fn new_err(py: Python<'_>, exc: MontyException) -> PyErr {
method traceback (line 246) | fn traceback(&self, py: Python<'_>) -> Py<PyList> {
method display (line 257) | fn display(slf: PyRef<'_, Self>, format: &str) -> PyResult<String> {
method __str__ (line 269) | fn __str__(slf: PyRef<'_, Self>) -> String {
method __repr__ (line 281) | fn __repr__(slf: PyRef<'_, Self>) -> String {
type PyFrame (line 299) | pub struct PyFrame {
method dict (line 325) | fn dict(&self, py: Python<'_>) -> Py<PyDict> {
method __repr__ (line 337) | fn __repr__(&self) -> String {
method from_stack_frame (line 349) | pub fn from_stack_frame(frame: &StackFrame) -> Self {
function exc_monty_to_py (line 367) | pub fn exc_monty_to_py(py: Python<'_>, exc: MontyException) -> PyErr {
function exc_py_to_monty (line 427) | pub fn exc_py_to_monty(py: Python<'_>, py_err: &PyErr) -> MontyException {
function exc_to_monty_object (line 436) | pub fn exc_to_monty_object(exc: &Bound<'_, exceptions::PyBaseException>)...
function py_err_to_exc_type (line 447) | fn py_err_to_exc_type(exc: &Bound<'_, exceptions::PyBaseException>) -> E...
function is_frozen_instance_error (line 541) | fn is_frozen_instance_error(exc: &Bound<'_, exceptions::PyBaseException>...
function get_re_pattern_error (line 549) | fn get_re_pattern_error(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>> {
FILE: crates/monty-python/src/external.rs
function dispatch_method_call (line 28) | pub fn dispatch_method_call(
function dispatch_method_call_inner (line 42) | fn dispatch_method_call_inner(
type ExternalFunctionRegistry (line 91) | pub struct ExternalFunctionRegistry<'a, 'py> {
function new (line 99) | pub fn new(py: Python<'py>, functions: &'py Bound<'py, PyDict>, dc_regis...
function call (line 114) | pub fn call(
function call_inner (line 128) | fn call_inner(
FILE: crates/monty-python/src/lib.rs
function get_version (line 25) | fn get_version() -> &'static str {
function init (line 73) | fn init(m: &Bound<'_, PyModule>) -> PyResult<()> {
FILE: crates/monty-python/src/limits.rs
function extract_limits (line 29) | pub fn extract_limits(dict: &Bound<'_, PyDict>) -> PyResult<monty::Resou...
function extract_optional_usize (line 56) | fn extract_optional_usize(dict: &Bound<'_, PyDict>, key: &str) -> PyResu...
function extract_optional_f64 (line 65) | fn extract_optional_f64(dict: &Bound<'_, PyDict>, key: &str) -> PyResult...
constant SIGNAL_CHECK_INTERVAL (line 78) | const SIGNAL_CHECK_INTERVAL: u16 = 1000;
type PySignalTracker (line 86) | pub struct PySignalTracker<T: ResourceTracker> {
function new (line 97) | pub fn new(inner: T) -> Self {
function check_python_signals (line 104) | fn check_python_signals(&self) -> Result<(), ResourceError> {
method on_allocate (line 119) | fn on_allocate(&mut self, get_size: impl FnOnce() -> usize) -> Result<()...
method on_free (line 123) | fn on_free(&mut self, get_size: impl FnOnce() -> usize) {
method check_time (line 127) | fn check_time(&self) -> Result<(), ResourceError> {
method check_recursion_depth (line 135) | fn check_recursion_depth(&self, current_depth: usize) -> Result<(), Reso...
method check_large_result (line 139) | fn check_large_result(&self, estimated_bytes: usize) -> Result<(), Resou...
FILE: crates/monty-python/src/monty_cls.rs
type PyMonty (line 40) | pub struct PyMonty {
method new (line 66) | fn new(
method register_dataclass (line 102) | fn register_dataclass(&self, cls: &Bound<'_, PyType>) -> PyResult<()> {
method type_check (line 119) | fn type_check(&self, py: Python<'_>, prefix_code: Option<&str>) -> PyR...
method run (line 131) | fn run(
method start (line 172) | fn start<'py>(
method dump (line 230) | fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
method load (line 253) | fn load(
method __repr__ (line 270) | fn __repr__(&self) -> String {
method extract_input_values (line 305) | fn extract_input_values(
method run_impl (line 342) | fn run_impl(
function py_type_check (line 286) | fn py_type_check(py: Python<'_>, code: &str, script_name: &str, type_stu...
type EitherProgress (line 455) | pub(crate) enum EitherProgress {
method progress_or_complete (line 467) | pub(crate) fn progress_or_complete(
function run_progress_to_py (line 484) | fn run_progress_to_py<T: ResourceTracker>(
function repl_progress_to_py (line 515) | fn repl_progress_to_py<T: ResourceTracker>(
type EitherFunctionSnapshot (line 574) | pub(crate) enum EitherFunctionSnapshot {
method from_fn (line 596) | fn from_fn(call: FunctionCall<PySignalTracker<NoLimitTracker>>) -> Self {
method from_fn (line 602) | fn from_fn(call: FunctionCall<PySignalTracker<LimitedTracker>>) -> Self {
method from_os (line 614) | fn from_os(call: OsCall<PySignalTracker<NoLimitTracker>>) -> Self {
method from_os (line 620) | fn from_os(call: OsCall<PySignalTracker<LimitedTracker>>) -> Self {
method from_repl_fn (line 632) | fn from_repl_fn(call: ReplFunctionCall<PySignalTracker<NoLimitTracker>...
method from_repl_fn (line 638) | fn from_repl_fn(call: ReplFunctionCall<PySignalTracker<LimitedTracker>...
method from_repl_os (line 650) | fn from_repl_os(call: ReplOsCall<PySignalTracker<NoLimitTracker>>, own...
method from_repl_os (line 656) | fn from_repl_os(call: ReplOsCall<PySignalTracker<LimitedTracker>>, own...
type FromFunctionCall (line 590) | trait FromFunctionCall<T: ResourceTracker> {
method from_fn (line 592) | fn from_fn(call: FunctionCall<T>) -> Self;
type FromOsCall (line 608) | trait FromOsCall<T: ResourceTracker> {
method from_os (line 610) | fn from_os(call: OsCall<T>) -> Self;
type FromReplFunctionCall (line 626) | trait FromReplFunctionCall<T: ResourceTracker> {
method from_repl_fn (line 628) | fn from_repl_fn(call: ReplFunctionCall<T>, owner: Py<PyMontyRepl>) -> ...
type FromReplOsCall (line 644) | trait FromReplOsCall<T: ResourceTracker> {
method from_repl_os (line 646) | fn from_repl_os(call: ReplOsCall<T>, owner: Py<PyMontyRepl>) -> Self;
type PyFunctionSnapshot (line 664) | pub struct PyFunctionSnapshot {
method function_call (line 700) | fn function_call<T: ResourceTracker>(
method os_call (line 742) | fn os_call<T: ResourceTracker>(
method repl_function_call (line 780) | fn repl_function_call<T: ResourceTracker>(
method repl_os_call (line 820) | fn repl_os_call<T: ResourceTracker>(
method from_deserialized (line 862) | pub(crate) fn from_deserialized(
method resume (line 901) | pub fn resume<'py>(&self, py: Python<'py>, kwargs: Option<&Bound<'_, P...
method dump (line 994) | fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
method __repr__ (line 1010) | fn __repr__(&self, py: Python<'_>) -> PyResult<String> {
type EitherLookupSnapshot (line 1028) | pub(crate) enum EitherLookupSnapshot {
method from_name_lookup (line 1044) | fn from_name_lookup(lookup: NameLookup<PySignalTracker<NoLimitTracker>...
method from_name_lookup (line 1050) | fn from_name_lookup(lookup: NameLookup<PySignalTracker<LimitedTracker>...
method from_repl_name_lookup (line 1062) | fn from_repl_name_lookup(lookup: ReplNameLookup<PySignalTracker<NoLimi...
method from_repl_name_lookup (line 1068) | fn from_repl_name_lookup(lookup: ReplNameLookup<PySignalTracker<Limite...
type FromNameLookup (line 1038) | trait FromNameLookup<T: ResourceTracker> {
method from_name_lookup (line 1040) | fn from_name_lookup(lookup: NameLookup<T>) -> Self;
type FromReplNameLookup (line 1056) | trait FromReplNameLookup<T: ResourceTracker> {
method from_repl_name_lookup (line 1058) | fn from_repl_name_lookup(lookup: ReplNameLookup<T>, owner: Py<PyMontyR...
type PyNameLookupSnapshot (line 1076) | pub struct PyNameLookupSnapshot {
method new_py_any (line 1095) | fn new_py_any<T: ResourceTracker>(
method repl_name_lookup (line 1118) | fn repl_name_lookup<T: ResourceTracker>(
method from_deserialized (line 1141) | pub(crate) fn from_deserialized(
method resume (line 1164) | pub fn resume<'py>(&self, py: Python<'py>, kwargs: Option<&Bound<'_, P...
method dump (line 1237) | fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
method __repr__ (line 1242) | fn __repr__(&self) -> String {
type EitherFutureSnapshot (line 1257) | pub(crate) enum EitherFutureSnapshot {
method from_resolve_futures (line 1273) | fn from_resolve_futures(state: ResolveFutures<PySignalTracker<NoLimitT...
method from_resolve_futures (line 1279) | fn from_resolve_futures(state: ResolveFutures<PySignalTracker<LimitedT...
method from_repl_resolve_futures (line 1291) | fn from_repl_resolve_futures(
method from_repl_resolve_futures (line 1300) | fn from_repl_resolve_futures(
type FromResolveFutures (line 1267) | trait FromResolveFutures<T: ResourceTracker> {
method from_resolve_futures (line 1269) | fn from_resolve_futures(state: ResolveFutures<T>) -> Self;
type FromReplResolveFutures (line 1285) | trait FromReplResolveFutures<T: ResourceTracker> {
method from_repl_resolve_futures (line 1287) | fn from_repl_resolve_futures(state: ReplResolveFutures<T>, owner: Py<P...
type PyFutureSnapshot (line 1313) | pub struct PyFutureSnapshot {
method new_py_any (line 1324) | fn new_py_any<T: ResourceTracker>(
method from_deserialized (line 1346) | pub(crate) fn from_deserialized(
method repl_resolve_futures (line 1363) | fn repl_resolve_futures<T: ResourceTracker>(
method resume (line 1388) | pub fn resume<'py>(&self, py: Python<'py>, results: &Bound<'_, PyDict>...
method pending_call_ids (line 1458) | fn pending_call_ids<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py...
method dump (line 1482) | fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
method __repr__ (line 1487) | fn __repr__(&self) -> String {
type PyMontyComplete (line 1504) | pub struct PyMontyComplete {
method create (line 1511) | fn create<'py>(py: Python<'py>, output: &MontyObject, dc_registry: &Dc...
method __repr__ (line 1520) | fn __repr__(&self, py: Python<'_>) -> PyResult<String> {
function list_str (line 1525) | fn list_str(arg: Option<&Bound<'_, PyList>>, name: &str) -> PyResult<Vec...
type CallbackStringPrint (line 1543) | pub(crate) struct CallbackStringPrint(Py<PyAny>);
method new (line 1547) | fn new(callback: &Bound<'_, PyAny>) -> Self {
method from_py (line 1552) | pub(crate) fn from_py(callback: Py<PyAny>) -> Self {
method stdout_write (line 1558) | fn stdout_write(&mut self, output: Cow<'_, str>) -> Result<(), MontyExce...
method stdout_push (line 1566) | fn stdout_push(&mut self, end: char) -> Result<(), MontyException> {
function contains_dataclass (line 1581) | fn contains_dataclass(obj: &MontyObject) -> bool {
type SerializedMonty (line 1594) | struct SerializedMonty {
function extract_external_result (line 1608) | fn extract_external_result(
function restore_repl_from_repl_start_error (line 1640) | fn restore_repl_from_repl_start_error<T: ResourceTracker>(
FILE: crates/monty-python/src/repl.rs
type EitherRepl (line 30) | pub(crate) enum EitherRepl {
method from_core (line 461) | fn from_core(repl: CoreMontyRepl<PySignalTracker<NoLimitTracker>>) -> ...
method from_core (line 467) | fn from_core(repl: CoreMontyRepl<PySignalTracker<LimitedTracker>>) -> ...
type PyMontyRepl (line 45) | pub struct PyMontyRepl {
method new (line 62) | fn new(
method register_dataclass (line 87) | fn register_dataclass(&self, cls: &Bound<'_, pyo3::types::PyType>) -> ...
method feed_run (line 100) | fn feed_run<'py>(
method feed_start (line 151) | fn feed_start<'py>(
method dump (line 198) | fn dump<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
method load (line 221) | fn load(
method __repr__ (line 242) | fn __repr__(&self) -> String {
method feed_run_with_externals (line 255) | fn feed_run_with_externals<'py>(
method feed_start_loop (line 291) | fn feed_start_loop<T: ResourceTracker + Send>(
method take_repl (line 394) | pub(crate) fn take_repl(&self) -> PyResult<EitherRepl> {
method empty_owner (line 409) | pub(crate) fn empty_owner(script_name: String, dc_registry: DcRegistry...
method put_repl (line 418) | pub(crate) fn put_repl(&self, repl: EitherRepl) {
method restore_repl_from_start_error (line 425) | fn restore_repl_from_start_error<T: ResourceTracker>(&self, py: Python...
function extract_repl_inputs (line 436) | fn extract_repl_inputs(
type FromCoreRepl (line 455) | pub(crate) trait FromCoreRepl<T: ResourceTracker> {
method from_core (line 457) | fn from_core(repl: CoreMontyRepl<T>) -> Self;
FILE: crates/monty-python/src/serialization.rs
constant SERIALIZATION_VERSION (line 38) | const SERIALIZATION_VERSION: u16 = 1;
constant HEADER_SIZE (line 41) | const HEADER_SIZE: usize = 2 + 32;
function serialize_with_header (line 50) | fn serialize_with_header(value: &impl Serialize) -> Result<Vec<u8>, post...
function deserialize_with_header (line 63) | fn deserialize_with_header<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -...
type SerializedSnapshot (line 100) | pub(crate) enum SerializedSnapshot {
type SerializedReplSnapshot (line 134) | pub(crate) enum SerializedReplSnapshot {
type SerdeFunctionSnapshot (line 171) | pub(crate) enum SerdeFunctionSnapshot {
method into_either (line 202) | fn into_either(self) -> PyResult<EitherFunctionSnapshot> {
method into_either_with_repl (line 219) | fn into_either_with_repl(self, owner: Py<PyMontyRepl>) -> EitherFuncti...
type SerdeFunctionSnapshotRef (line 185) | enum SerdeFunctionSnapshotRef<'a> {
method as_serde_ref (line 236) | fn as_serde_ref(&self) -> SerdeFunctionSnapshotRef<'_> {
type SerdeLookupSnapshot (line 253) | pub(crate) enum SerdeLookupSnapshot {
method into_either (line 273) | fn into_either(self) -> PyResult<EitherLookupSnapshot> {
method into_either_with_repl (line 285) | fn into_either_with_repl(self, owner: Py<PyMontyRepl>) -> EitherLookup...
type SerdeLookupSnapshotRef (line 263) | enum SerdeLookupSnapshotRef<'a> {
method as_serde_ref (line 298) | fn as_serde_ref(&self) -> SerdeLookupSnapshotRef<'_> {
type SerdeFutureSnapshot (line 311) | pub(crate) enum SerdeFutureSnapshot {
method into_either (line 331) | fn into_either(self) -> PyResult<EitherFutureSnapshot> {
method into_either_with_repl (line 343) | fn into_either_with_repl(self, owner: Py<PyMontyRepl>) -> EitherFuture...
type SerdeFutureSnapshotRef (line 321) | enum SerdeFutureSnapshotRef<'a> {
method as_serde_ref (line 356) | fn as_serde_ref(&self) -> SerdeFutureSnapshotRef<'_> {
function dump_function_snapshot (line 376) | pub(crate) fn dump_function_snapshot(
function dump_lookup_snapshot (line 428) | pub(crate) fn dump_lookup_snapshot(
function dump_future_snapshot (line 460) | pub(crate) fn dump_future_snapshot(
type SerializedSnapshotRef (line 494) | enum SerializedSnapshotRef<'a> {
type SerializedReplSnapshotRef (line 518) | enum SerializedReplSnapshotRef<'a> {
function load_snapshot (line 550) | pub(crate) fn load_snapshot<'py>(
function load_repl_snapshot (line 609) | pub(crate) fn load_repl_snapshot<'py>(
function create_empty_py_repl (line 679) | fn create_empty_py_repl(py: Python<'_>, script_name: &str, dc_registry: ...
function convert_args_to_monty (line 689) | fn convert_args_to_monty(py: Python<'_>, args: &Py<PyTuple>, dc_registry...
function convert_kwargs_to_monty (line 697) | fn convert_kwargs_to_monty(
function monty_objects_to_py_tuple (line 710) | fn monty_objects_to_py_tuple(
function monty_pairs_to_py_dict (line 723) | fn monty_pairs_to_py_dict(
method is_repl (line 741) | pub(crate) fn is_repl(&self) -> bool {
method is_repl (line 751) | pub(crate) fn is_repl(&self) -> bool {
method is_repl (line 758) | pub(crate) fn is_repl(&self) -> bool {
FILE: crates/monty-python/tests/test_async.py
function test_async (line 11) | def test_async():
function test_asyncio_gather (line 27) | def test_asyncio_gather():
function test_run_monty_async_sync_function (line 76) | async def test_run_monty_async_sync_function():
function test_run_monty_async_async_function (line 87) | async def test_run_monty_async_async_function():
function test_run_monty_async_function_not_found (line 99) | async def test_run_monty_async_function_not_found():
function test_run_monty_async_sync_exception (line 110) | async def test_run_monty_async_sync_exception():
function test_run_monty_async_async_exception (line 124) | async def test_run_monty_async_async_exception():
function test_run_monty_async_exception_caught (line 139) | async def test_run_monty_async_exception_caught():
function test_run_monty_async_multiple_async_functions (line 157) | async def test_run_monty_async_multiple_async_functions():
function test_run_monty_async_mixed_sync_async (line 177) | async def test_run_monty_async_mixed_sync_async():
function test_run_monty_async_with_inputs (line 197) | async def test_run_monty_async_with_inputs():
function test_run_monty_async_with_print_callback (line 208) | async def test_run_monty_async_with_print_callback():
function test_run_monty_async_function_returning_none (line 221) | async def test_run_monty_async_function_returning_none():
function test_run_monty_async_no_external_calls (line 232) | async def test_run_monty_async_no_external_calls():
function test_run_monty_async_with_os (line 242) | async def test_run_monty_async_with_os():
function test_run_monty_async_os_with_external_functions (line 259) | async def test_run_monty_async_os_with_external_functions():
function test_run_monty_async_os_file_not_found (line 284) | async def test_run_monty_async_os_file_not_found():
function test_run_monty_async_os_not_provided (line 302) | async def test_run_monty_async_os_not_provided():
function test_run_monty_async_nested_gather_with_external_functions (line 319) | async def test_run_monty_async_nested_gather_with_external_functions():
function test_run_monty_async_os_write_and_read (line 393) | async def test_run_monty_async_os_write_and_read():
function test_repl_feed_start_async_gather (line 415) | def test_repl_feed_start_async_gather():
function test_repl_feed_start_async_state_persistence (line 446) | def test_repl_feed_start_async_state_persistence():
function test_run_repl_async_sync_function (line 470) | async def test_run_repl_async_sync_function():
function test_run_repl_async_async_function (line 481) | async def test_run_repl_async_async_function():
function test_run_repl_async_state_persists (line 493) | async def test_run_repl_async_state_persists():
function test_run_repl_async_async_state_persists (line 507) | async def test_run_repl_async_async_state_persists():
function test_run_repl_async_gather (line 521) | async def test_run_repl_async_gather():
function test_run_repl_async_function_not_found (line 541) | async def test_run_repl_async_function_not_found():
function test_run_repl_async_error_preserves_state (line 552) | async def test_run_repl_async_error_preserves_state():
function test_run_repl_async_with_inputs (line 567) | async def test_run_repl_async_with_inputs():
function test_run_repl_async_with_print_callback (line 578) | async def test_run_repl_async_with_print_callback():
function test_run_repl_async_with_os (line 590) | async def test_run_repl_async_with_os():
function test_run_repl_async_mixed_sync_async (line 605) | async def test_run_repl_async_mixed_sync_async():
function test_run_repl_async_no_external_calls (line 625) | async def test_run_repl_async_no_external_calls():
function test_repl_llm_iterative_data_collection (line 635) | async def test_repl_llm_iterative_data_collection():
function test_repl_llm_error_recovery_retry (line 691) | async def test_repl_llm_error_recovery_retry():
function test_repl_llm_redefine_helper_function (line 724) | async def test_repl_llm_redefine_helper_function():
function test_repl_llm_sequential_async_pipeline (line 771) | async def test_repl_llm_sequential_async_pipeline():
function test_repl_llm_gather_fan_out (line 802) | async def test_repl_llm_gather_fan_out():
function test_repl_llm_try_except_around_external (line 823) | async def test_repl_llm_try_except_around_external():
function test_repl_llm_conditional_external_call (line 847) | async def test_repl_llm_conditional_external_call():
function test_repl_llm_side_effect_recording (line 879) | async def test_repl_llm_side_effect_recording():
function test_repl_llm_helper_wrapping_externals_with_retry (line 908) | async def test_repl_llm_helper_wrapping_externals_with_retry():
function test_repl_llm_nested_gather_with_sequential_deps (line 944) | async def test_repl_llm_nested_gather_with_sequential_deps():
function test_repl_llm_external_returns_complex_nested_structure (line 982) | async def test_repl_llm_external_returns_complex_nested_structure():
function test_repl_llm_external_with_kwargs (line 1019) | async def test_repl_llm_external_with_kwargs():
function test_repl_llm_os_read_then_process_with_external (line 1037) | async def test_repl_llm_os_read_then_process_with_external():
function test_repl_llm_long_multi_step_session (line 1066) | async def test_repl_llm_long_multi_step_session():
function test_repl_llm_string_manipulation_of_external_result (line 1141) | async def test_repl_llm_string_manipulation_of_external_result():
function test_repl_llm_syntax_error_then_fix (line 1183) | async def test_repl_llm_syntax_error_then_fix():
FILE: crates/monty-python/tests/test_basic.py
function test_simple_expression (line 6) | def test_simple_expression():
function test_arithmetic (line 11) | def test_arithmetic():
function test_string_concatenation (line 16) | def test_string_concatenation():
function test_multiple_runs_same_instance (line 21) | def test_multiple_runs_same_instance():
function test_repr_no_inputs (line 28) | def test_repr_no_inputs():
function test_repr_with_inputs (line 33) | def test_repr_with_inputs():
function test_repr_with_external_functions (line 38) | def test_repr_with_external_functions():
function test_repr_with_inputs_and_external_functions (line 43) | def test_repr_with_inputs_and_external_functions():
function test_multiline_code (line 48) | def test_multiline_code():
function test_function_definition_and_call (line 58) | def test_function_definition_and_call():
FILE: crates/monty-python/tests/test_dataclasses.py
class Person (line 18) | class Person:
function test_dataclass_input (line 23) | def test_dataclass_input():
function test_dataclass_auto_registered (line 37) | def test_dataclass_auto_registered():
class Point (line 51) | class Point:
function test_dataclass_frozen (line 56) | def test_dataclass_frozen():
class Address (line 68) | class Address:
class PersonAddress (line 74) | class PersonAddress:
function test_dataclass_nested (line 79) | def test_dataclass_nested():
function test_dataclass_nested_auto_registered (line 93) | def test_dataclass_nested_auto_registered():
function test_dataclass_auto_registered_in_list (line 104) | def test_dataclass_auto_registered_in_list():
function test_dataclass_auto_registered_in_dict_value (line 113) | def test_dataclass_auto_registered_in_dict_value():
function test_dataclass_explicit_registry_idempotent (line 122) | def test_dataclass_explicit_registry_idempotent():
function test_dataclass_with_list_field (line 132) | def test_dataclass_with_list_field():
function test_dataclass_with_dict_field (line 144) | def test_dataclass_with_dict_field():
function test_dataclass_empty (line 157) | def test_dataclass_empty():
function test_dataclass_type_raises (line 171) | def test_dataclass_type_raises():
function test_dataclass_field_access (line 189) | def test_dataclass_field_access():
function test_dataclass_field_access_nested (line 204) | def test_dataclass_field_access_nested():
function test_dataclass_field_in_expression (line 212) | def test_dataclass_field_in_expression():
function test_dataclass_field_access_missing (line 224) | def test_dataclass_field_access_missing():
function test_dataclass_repr (line 240) | def test_dataclass_repr():
function test_dataclass_repr_frozen (line 252) | def test_dataclass_repr_frozen():
function test_dataclass_repr_nested (line 264) | def test_dataclass_repr_nested():
function test_dataclass_repr_empty (line 279) | def test_dataclass_repr_empty():
function test_dataclass_setattr_mutable (line 294) | def test_dataclass_setattr_mutable():
function test_dataclass_setattr_frozen (line 312) | def test_dataclass_setattr_frozen():
function test_frozen_instance_error_is_attribute_error (line 331) | def test_frozen_instance_error_is_attribute_error():
function test_frozen_instance_error_message (line 353) | def test_frozen_instance_error_message():
function test_frozen_instance_error_from_monty_code (line 369) | def test_frozen_instance_error_from_monty_code():
function test_frozen_instance_error_from_monty_caught_as_attribute_error (line 390) | def test_frozen_instance_error_from_monty_caught_as_attribute_error():
function test_frozen_instance_error_from_external_function (line 410) | def test_frozen_instance_error_from_external_function():
function test_frozen_instance_error_from_external_function_propagates (line 431) | def test_frozen_instance_error_from_external_function_propagates():
function test_dataclass_equality_same (line 448) | def test_dataclass_equality_same():
function test_dataclass_equality_different_values (line 461) | def test_dataclass_equality_different_values():
function test_dataclass_equality_different_types (line 474) | def test_dataclass_equality_different_types():
function test_dataclass_equality_with_other_type (line 492) | def test_dataclass_equality_with_other_type():
function test_dataclass_hash_frozen (line 510) | def test_dataclass_hash_frozen():
function test_dataclass_hash_frozen_equal_values (line 527) | def test_dataclass_hash_frozen_equal_values():
function test_dataclass_hash_mutable_raises (line 541) | def test_dataclass_hash_mutable_raises():
function test_dataclass_hash_in_set (line 556) | def test_dataclass_hash_in_set():
function test_dataclass_hash_as_dict_key (line 577) | def test_dataclass_hash_as_dict_key():
function test_dataclass_is_dataclass (line 595) | def test_dataclass_is_dataclass():
function test_dataclass_fields (line 608) | def test_dataclass_fields():
function test_dataclass_fields_string (line 628) | def test_dataclass_fields_string():
function test_dataclass_asdict (line 643) | def test_dataclass_asdict():
function test_dataclass_asdict_nested (line 658) | def test_dataclass_asdict_nested():
function test_dataclass_astuple (line 676) | def test_dataclass_astuple():
function test_dataclass_dataclass_fields_attr (line 691) | def test_dataclass_dataclass_fields_attr():
function test_dataclass_params_frozen (line 709) | def test_dataclass_params_frozen():
function test_dataclass_params_attributes (line 729) | def test_dataclass_params_attributes():
function test_repeat_dataclass_name (line 748) | def test_repeat_dataclass_name():
class Greeter (line 770) | class Greeter:
method greet (line 773) | def greet(self) -> str:
class Calculator (line 778) | class Calculator:
method add (line 781) | def add(self, n: int) -> int:
method multiply (line 784) | def multiply(self, n: int) -> int:
class Point2D (line 789) | class Point2D:
method distance (line 793) | def distance(self) -> float:
method translate (line 796) | def translate(self, dx: float, dy: float) -> 'Point2D':
function test_method_no_args_raw (line 800) | def test_method_no_args_raw():
function test_method_no_args (line 811) | def test_method_no_args():
function test_method_with_args (line 818) | def test_method_with_args():
function test_method_accessing_fields (line 825) | def test_method_accessing_fields():
function test_method_returning_dataclass (line 832) | def test_method_returning_dataclass():
function test_method_on_frozen_dataclass (line 841) | def test_method_on_frozen_dataclass():
function test_method_with_kwargs (line 856) | def test_method_with_kwargs():
function test_method_multiple_calls (line 875) | def test_method_multiple_calls():
function test_method_nonexistent_raises (line 886) | def test_method_nonexistent_raises():
function test_method_on_nested_dataclass_in_list (line 894) | def test_method_on_nested_dataclass_in_list():
function test_method_on_nested_dataclass_in_dict (line 901) | def test_method_on_nested_dataclass_in_dict():
function test_method_on_nested_dataclass_in_tuple (line 908) | def test_method_on_nested_dataclass_in_tuple():
function test_dataclass_private_fields_skipped (line 915) | def test_dataclass_private_fields_skipped():
function test_dataclass_private_fields_skipped_no_default (line 928) | def test_dataclass_private_fields_skipped_no_default():
function test_dataclass_private_field_not_accessible_in_monty (line 941) | def test_dataclass_private_field_not_accessible_in_monty():
function test_method_on_nested_dataclass_field (line 955) | def test_method_on_nested_dataclass_field():
FILE: crates/monty-python/tests/test_exceptions.py
function test_zero_division_error (line 9) | def test_zero_division_error():
function test_value_error (line 20) | def test_value_error():
function test_type_error (line 29) | def test_type_error():
function test_index_error (line 37) | def test_index_error():
function test_key_error (line 45) | def test_key_error():
function test_attribute_error (line 53) | def test_attribute_error():
function test_name_error (line 62) | def test_name_error():
function test_assertion_error (line 70) | def test_assertion_error():
function test_assertion_error_with_message (line 78) | def test_assertion_error_with_message():
function test_runtime_error (line 87) | def test_runtime_error():
function test_not_implemented_error (line 96) | def test_not_implemented_error():
function test_syntax_error_on_init (line 108) | def test_syntax_error_on_init():
function test_syntax_error_unclosed_paren (line 118) | def test_syntax_error_unclosed_paren():
function test_syntax_error_invalid_syntax (line 125) | def test_syntax_error_invalid_syntax():
function test_catch_with_base_class (line 135) | def test_catch_with_base_class():
function test_catch_syntax_error_with_base_class (line 141) | def test_catch_syntax_error_with_base_class():
function test_raise_caught_exception (line 149) | def test_raise_caught_exception():
function test_exception_in_function (line 161) | def test_exception_in_function():
function test_display_traceback (line 179) | def test_display_traceback():
function test_display_type_msg (line 188) | def test_display_type_msg():
function test_runtime_display (line 196) | def test_runtime_display():
function test_str_returns_msg (line 210) | def test_str_returns_msg():
function test_syntax_error_display (line 217) | def test_syntax_error_display():
function test_syntax_error_str (line 224) | def test_syntax_error_str():
function test_traceback_frames (line 234) | def test_traceback_frames():
function test_frame_properties (line 297) | def test_frame_properties():
function test_runtime_error_repr (line 336) | def test_runtime_error_repr():
function test_syntax_error_repr (line 343) | def test_syntax_error_repr():
function test_frame_repr (line 349) | def test_frame_repr():
FILE: crates/monty-python/tests/test_external.py
function test_external_function_no_args (line 9) | def test_external_function_no_args():
function test_external_function_positional_args (line 20) | def test_external_function_positional_args():
function test_external_function_kwargs_only (line 31) | def test_external_function_kwargs_only():
function test_external_function_mixed_args_kwargs (line 42) | def test_external_function_mixed_args_kwargs():
function test_external_function_complex_types (line 53) | def test_external_function_complex_types():
function test_external_function_returns_none (line 64) | def test_external_function_returns_none():
function test_external_function_returns_complex_type (line 74) | def test_external_function_returns_complex_type():
function test_multiple_external_functions (line 84) | def test_multiple_external_functions():
function test_external_function_called_multiple_times (line 101) | def test_external_function_called_multiple_times():
function test_external_function_with_input (line 118) | def test_external_function_with_input():
function test_external_function_not_provided_raises_name_error (line 129) | def test_external_function_not_provided_raises_name_error():
function test_undeclared_function_raises_name_error (line 140) | def test_undeclared_function_raises_name_error():
function test_external_function_raises_exception (line 150) | def test_external_function_raises_exception():
function test_external_function_wrong_name_raises (line 164) | def test_external_function_wrong_name_raises():
function test_external_function_exception_caught_by_try_except (line 178) | def test_external_function_exception_caught_by_try_except():
function test_external_function_exception_type_preserved (line 196) | def test_external_function_exception_type_preserved():
function test_external_function_exception_hierarchy (line 233) | def test_external_function_exception_hierarchy(exception_class: type[Bas...
function test_external_function_exception_caught_by_parent (line 261) | def test_external_function_exception_caught_by_parent(
function test_external_function_exception_caught_specifically (line 295) | def test_external_function_exception_caught_specifically(exception_class...
function test_external_function_exception_in_expression (line 313) | def test_external_function_exception_in_expression():
function test_external_function_exception_after_successful_call (line 327) | def test_external_function_exception_after_successful_call():
function test_external_function_exception_with_finally (line 349) | def test_external_function_exception_with_finally():
FILE: crates/monty-python/tests/test_inputs.py
function test_single_input (line 7) | def test_single_input():
function test_multiple_inputs (line 12) | def test_multiple_inputs():
function test_input_used_in_expression (line 17) | def test_input_used_in_expression():
function test_input_string (line 22) | def test_input_string():
function test_input_list (line 27) | def test_input_list():
function test_input_dict (line 32) | def test_input_dict():
function test_missing_input_raises (line 37) | def test_missing_input_raises():
function test_all_inputs_missing_raises (line 43) | def test_all_inputs_missing_raises():
function test_no_inputs_declared_but_provided_raises (line 49) | def test_no_inputs_declared_but_provided_raises():
function test_inputs_order_independent (line 57) | def test_inputs_order_independent():
function test_function_param_shadows_input (line 63) | def test_function_param_shadows_input():
function test_function_param_shadows_input_multiple_params (line 76) | def test_function_param_shadows_input_multiple_params():
function test_input_accessible_outside_shadowing_function (line 89) | def test_input_accessible_outside_shadowing_function():
function test_function_param_shadows_input_with_default (line 103) | def test_function_param_shadows_input_with_default():
function test_function_uses_input_directly (line 116) | def test_function_uses_input_directly():
FILE: crates/monty-python/tests/test_limits.py
function test_resource_limits_custom (line 14) | def test_resource_limits_custom():
function test_resource_limits_repr (line 29) | def test_resource_limits_repr():
function test_run_with_limits (line 34) | def test_run_with_limits():
function test_recursion_limit (line 40) | def test_recursion_limit():
function test_recursion_limit_ok (line 56) | def test_recursion_limit_ok():
function test_allocation_limit (line 70) | def test_allocation_limit():
function test_memory_limit (line 86) | def test_memory_limit():
function test_limits_with_inputs (line 100) | def test_limits_with_inputs():
function test_limits_wrong_type_raises_error (line 106) | def test_limits_wrong_type_raises_error():
function test_limits_none_value_allowed (line 112) | def test_limits_none_value_allowed():
function test_signal_alarm_custom_error (line 118) | def test_signal_alarm_custom_error():
function _send_sigint_after_delay (line 157) | def _send_sigint_after_delay(pid: int, delay: float) -> None:
function test_keyboard_interrupt (line 163) | def test_keyboard_interrupt():
function test_pow_memory_limit (line 191) | def test_pow_memory_limit():
function test_lshift_memory_limit (line 200) | def test_lshift_memory_limit():
function test_mult_memory_limit (line 209) | def test_mult_memory_limit():
function test_small_operations_within_limit (line 223) | def test_small_operations_within_limit():
function test_timeout_enforced_in_builtin_loops (line 242) | def test_timeout_enforced_in_builtin_loops(code: str):
FILE: crates/monty-python/tests/test_os_access.py
function test_non_absolute_path (line 26) | def test_non_absolute_path():
function test_file_nested_within_file_rejected (line 35) | def test_file_nested_within_file_rejected():
function test_empty_initialization (line 50) | def test_empty_initialization():
function test_environ_parameter (line 57) | def test_environ_parameter():
function test_path_exists_file (line 69) | def test_path_exists_file():
function test_path_exists_directory (line 76) | def test_path_exists_directory():
function test_path_exists_nested (line 83) | def test_path_exists_nested():
function test_path_exists_missing (line 94) | def test_path_exists_missing():
function test_path_is_file_for_file (line 101) | def test_path_is_file_for_file():
function test_path_is_file_for_directory (line 108) | def test_path_is_file_for_directory():
function test_path_is_file_missing (line 115) | def test_path_is_file_missing():
function test_path_is_dir_for_directory (line 122) | def test_path_is_dir_for_directory():
function test_path_is_dir_for_file (line 129) | def test_path_is_dir_for_file():
function test_path_is_dir_missing (line 136) | def test_path_is_dir_missing():
function test_path_is_symlink_always_false (line 143) | def test_path_is_symlink_always_false():
function test_read_text_string_content (line 159) | def test_read_text_string_content():
function test_read_text_bytes_content_decoded (line 166) | def test_read_text_bytes_content_decoded():
function test_read_bytes_bytes_content (line 173) | def test_read_bytes_bytes_content():
function test_read_bytes_string_content_encoded (line 180) | def test_read_bytes_string_content_encoded():
function test_read_text_file_not_found (line 187) | def test_read_text_file_not_found():
function test_read_bytes_file_not_found (line 195) | def test_read_bytes_file_not_found():
function test_read_text_is_a_directory (line 203) | def test_read_text_is_a_directory():
function test_read_bytes_is_a_directory (line 212) | def test_read_bytes_is_a_directory():
function test_write_text_via_monty (line 226) | def test_write_text_via_monty():
function test_write_text_overwrite_via_monty (line 243) | def test_write_text_overwrite_via_monty():
function test_write_bytes_via_monty (line 255) | def test_write_bytes_via_monty():
function test_write_text_parent_not_exists_via_monty (line 268) | def test_write_text_parent_not_exists_via_monty():
function test_write_text_to_directory_via_monty (line 278) | def test_write_text_to_directory_via_monty():
function test_write_text_new_file_direct (line 291) | def test_write_text_new_file_direct():
function test_write_text_overwrite_existing_direct (line 303) | def test_write_text_overwrite_existing_direct():
function test_write_bytes_new_file_direct (line 311) | def test_write_bytes_new_file_direct():
function test_write_bytes_overwrite_existing_direct (line 319) | def test_write_bytes_overwrite_existing_direct():
function test_write_text_parent_not_exists_direct (line 327) | def test_write_text_parent_not_exists_direct():
function test_write_text_to_directory_direct (line 335) | def test_write_text_to_directory_direct():
function test_mkdir_basic_via_monty (line 348) | def test_mkdir_basic_via_monty():
function test_mkdir_with_parents_via_monty (line 360) | def test_mkdir_with_parents_via_monty():
function test_mkdir_exist_ok_true_via_monty (line 375) | def test_mkdir_exist_ok_true_via_monty():
function test_mkdir_exist_ok_false_via_monty (line 388) | def test_mkdir_exist_ok_false_via_monty():
function test_mkdir_parent_not_exists_via_monty (line 398) | def test_mkdir_parent_not_exists_via_monty():
function test_mkdir_basic_direct (line 412) | def test_mkdir_basic_direct():
function test_mkdir_with_parents_direct (line 420) | def test_mkdir_with_parents_direct():
function test_mkdir_exist_ok_true_direct (line 431) | def test_mkdir_exist_ok_true_direct():
function test_mkdir_exist_ok_false_direct (line 440) | def test_mkdir_exist_ok_false_direct():
function test_mkdir_file_exists_direct (line 449) | def test_mkdir_file_exists_direct():
function test_mkdir_parent_not_exists_direct (line 458) | def test_mkdir_parent_not_exists_direct():
function test_mkdir_parent_is_file_direct (line 467) | def test_mkdir_parent_is_file_direct():
function test_rmdir_empty_directory_via_monty (line 481) | def test_rmdir_empty_directory_via_monty():
function test_rmdir_non_empty_directory_via_monty (line 494) | def test_rmdir_non_empty_directory_via_monty():
function test_rmdir_not_found_via_monty (line 503) | def test_rmdir_not_found_via_monty():
function test_rmdir_file_not_directory_via_monty (line 512) | def test_rmdir_file_not_directory_via_monty():
function test_rmdir_empty_directory_direct (line 526) | def test_rmdir_empty_directory_direct():
function test_rmdir_non_empty_directory_direct (line 535) | def test_rmdir_non_empty_directory_direct():
function test_rmdir_file_not_directory_direct (line 544) | def test_rmdir_file_not_directory_direct():
function test_rmdir_not_found_direct (line 553) | def test_rmdir_not_found_direct():
function test_iterdir_list_contents (line 567) | def test_iterdir_list_contents():
function test_iterdir_empty_directory_direct (line 585) | def test_iterdir_empty_directory_direct():
function test_iterdir_not_a_directory_direct (line 594) | def test_iterdir_not_a_directory_direct():
function test_iterdir_not_found (line 603) | def test_iterdir_not_found():
function test_unlink_file_via_monty (line 616) | def test_unlink_file_via_monty():
function test_unlink_file_not_found_via_monty (line 628) | def test_unlink_file_not_found_via_monty():
function test_unlink_is_directory_via_monty (line 637) | def test_unlink_is_directory_via_monty():
function test_unlink_file_direct (line 651) | def test_unlink_file_direct():
function test_unlink_file_not_found_direct (line 659) | def test_unlink_file_not_found_direct():
function test_unlink_is_directory_direct (line 668) | def test_unlink_is_directory_direct():
function test_stat_file (line 682) | def test_stat_file():
function test_stat_file_custom_permissions (line 694) | def test_stat_file_custom_permissions():
function test_stat_directory (line 706) | def test_stat_directory():
function test_stat_file_not_found (line 719) | def test_stat_file_not_found():
function test_stat_bytes_content_size (line 727) | def test_stat_bytes_content_size():
function test_stat_unicode_size (line 738) | def test_stat_unicode_size():
function test_rename_file_via_monty (line 755) | def test_rename_file_via_monty():
function test_rename_source_not_found_via_monty (line 770) | def test_rename_source_not_found_via_monty():
function test_rename_target_parent_not_found_via_monty (line 781) | def test_rename_target_parent_not_found_via_monty():
function test_rename_file_direct (line 797) | def test_rename_file_direct():
function test_rename_source_not_found_direct (line 808) | def test_rename_source_not_found_direct():
function test_rename_target_parent_not_found_direct (line 817) | def test_rename_target_parent_not_found_direct():
function test_rename_directory_direct (line 828) | def test_rename_directory_direct():
function test_rename_directory_non_empty_target_direct (line 837) | def test_rename_directory_non_empty_target_direct():
function test_rename_directory_updates_file_paths_direct (line 851) | def test_rename_directory_updates_file_paths_direct():
function test_path_resolve_absolute (line 879) | def test_path_resolve_absolute():
function test_path_absolute_already_absolute (line 890) | def test_path_absolute_already_absolute():
function test_path_absolute_relative (line 901) | def test_path_absolute_relative():
function test_path_resolve_same_as_absolute (line 912) | def test_path_resolve_same_as_absolute():
function test_getenv_existing_key (line 928) | def test_getenv_existing_key():
function test_getenv_missing_key (line 935) | def test_getenv_missing_key():
function test_getenv_missing_with_default (line 942) | def test_getenv_missing_with_default():
function test_getenv_multiple_vars (line 949) | def test_getenv_multiple_vars():
function test_get_environ_returns_dict (line 960) | def test_get_environ_returns_dict():
function test_get_environ_key_access (line 967) | def test_get_environ_key_access():
function test_get_environ_key_missing_raises (line 974) | def test_get_environ_key_missing_raises():
function test_get_environ_get_method (line 982) | def test_get_environ_get_method():
function test_get_environ_get_missing_with_default (line 989) | def test_get_environ_get_missing_with_default():
function test_get_environ_len (line 996) | def test_get_environ_len():
function test_get_environ_contains (line 1003) | def test_get_environ_contains():
function test_get_environ_keys (line 1014) | def test_get_environ_keys():
function test_get_environ_values (line 1021) | def test_get_environ_values():
function test_get_environ_items (line 1028) | def test_get_environ_items():
function test_get_environ_empty (line 1035) | def test_get_environ_empty():
function test_memory_file_string_content (line 1047) | def test_memory_file_string_content():
function test_memory_file_bytes_content (line 1055) | def test_memory_file_bytes_content():
function test_memory_file_custom_permissions (line 1061) | def test_memory_file_custom_permissions():
function test_memory_file_write_and_read (line 1067) | def test_memory_file_write_and_read():
function test_memory_file_delete (line 1074) | def test_memory_file_delete():
function test_memory_file_repr (line 1082) | def test_memory_file_repr():
function test_memory_file_bytes_repr (line 1088) | def test_memory_file_bytes_repr():
function test_callback_file_read (line 1099) | def test_callback_file_read():
function test_callback_file_write_direct (line 1118) | def test_callback_file_write_direct():
function test_callback_file_custom_permissions (line 1137) | def test_callback_file_custom_permissions():
function test_callback_file_repr (line 1148) | def test_callback_file_repr():
class CustomFile (line 1159) | class CustomFile:
method __init__ (line 1162) | def __init__(self, path: str, content: str) -> None:
method read_content (line 1169) | def read_content(self) -> str:
method write_content (line 1172) | def write_content(self, content: str | bytes) -> None:
method delete (line 1175) | def delete(self) -> None:
function test_custom_abstract_file (line 1179) | def test_custom_abstract_file():
function test_custom_abstract_file_mixed_with_memory_file (line 1188) | def test_custom_abstract_file_mixed_with_memory_file():
function test_os_access_direct_api (line 1207) | def test_os_access_direct_api():
function test_root_directory (line 1248) | def test_root_directory():
function test_empty_file (line 1259) | def test_empty_file():
function test_large_nested_path (line 1270) | def test_large_nested_path():
function test_special_characters_in_content (line 1281) | def test_special_characters_in_content():
FILE: crates/monty-python/tests/test_os_access_compat.py
class CodeRunner (line 25) | class CodeRunner(ABC):
method write_file (line 33) | def write_file(self, path: str, content: str | bytes) -> None:
method run_code (line 42) | def run_code(self, code: str) -> Any:
method tree (line 59) | def tree(self) -> TreeDict:
method set_environ (line 69) | def set_environ(self, environ: dict[str, str]) -> None:
class MontyRunner (line 77) | class MontyRunner(CodeRunner):
method __init__ (line 80) | def __init__(self) -> None:
method write_file (line 85) | def write_file(self, path: str, content: str | bytes) -> None:
method set_environ (line 91) | def set_environ(self, environ: dict[str, str]) -> None:
method _get_os_access (line 96) | def _get_os_access(self) -> OSAccess:
method run_code (line 101) | def run_code(self, code: str) -> Any:
method tree (line 107) | def tree(self) -> TreeDict:
class CPythonRunner (line 131) | class CPythonRunner(CodeRunner):
method __init__ (line 134) | def __init__(self, tmp_path: Path) -> None:
method write_file (line 138) | def write_file(self, path: str, content: str | bytes) -> None:
method set_environ (line 146) | def set_environ(self, environ: dict[str, str]) -> None:
method run_code (line 149) | def run_code(self, code: str) -> Any:
method tree (line 186) | def tree(self) -> TreeDict:
function runner (line 207) | def runner(request: pytest.FixtureRequest, tmp_path: Path) -> CodeRunner:
function test_path_exists_file (line 220) | def test_path_exists_file(runner: CodeRunner) -> None:
function test_path_exists_directory (line 227) | def test_path_exists_directory(runner: CodeRunner) -> None:
function test_path_exists_missing (line 234) | def test_path_exists_missing(runner: CodeRunner) -> None:
function test_path_is_file (line 240) | def test_path_is_file(runner: CodeRunner) -> None:
function test_path_is_dir (line 247) | def test_path_is_dir(runner: CodeRunner) -> None:
function test_read_text (line 259) | def test_read_text(runner: CodeRunner) -> None:
function test_read_bytes (line 266) | def test_read_bytes(runner: CodeRunner) -> None:
function test_read_text_unicode (line 273) | def test_read_text_unicode(runner: CodeRunner) -> None:
function test_tree_simple (line 285) | def test_tree_simple(runner: CodeRunner) -> None:
function test_tree_nested (line 292) | def test_tree_nested(runner: CodeRunner) -> None:
function test_tree_mixed (line 298) | def test_tree_mixed(runner: CodeRunner) -> None:
function test_stat_size (line 311) | def test_stat_size(runner: CodeRunner) -> None:
function test_stat_size_unicode (line 318) | def test_stat_size_unicode(runner: CodeRunner) -> None:
function test_iterdir (line 331) | def test_iterdir(runner: CodeRunner) -> None:
function test_read_text_file_not_found (line 357) | def test_read_text_file_not_found(runner: CodeRunner) -> None:
function test_read_bytes_file_not_found (line 370) | def test_read_bytes_file_not_found(runner: CodeRunner) -> None:
function test_stat_file_not_found (line 383) | def test_stat_file_not_found(runner: CodeRunner) -> None:
function test_iterdir_not_found (line 396) | def test_iterdir_not_found(runner: CodeRunner) -> None:
function test_read_text_is_directory (line 414) | def test_read_text_is_directory(runner: CodeRunner) -> None:
function test_read_bytes_is_directory (line 428) | def test_read_bytes_is_directory(runner: CodeRunner) -> None:
function test_iterdir_not_a_directory (line 447) | def test_iterdir_not_a_directory(runner: CodeRunner) -> None:
function test_mkdir_file_exists (line 466) | def test_mkdir_file_exists(runner: CodeRunner) -> None:
function test_mkdir_file_at_path (line 480) | def test_mkdir_file_at_path(runner: CodeRunner) -> None:
function test_mkdir_exist_ok_no_error (line 494) | def test_mkdir_exist_ok_no_error(runner: CodeRunner) -> None:
function test_mkdir_parent_not_found (line 509) | def test_mkdir_parent_not_found(runner: CodeRunner) -> None:
function test_mkdir_parents_creates_all (line 522) | def test_mkdir_parents_creates_all(runner: CodeRunner) -> None:
function test_unlink_file_not_found (line 536) | def test_unlink_file_not_found(runner: CodeRunner) -> None:
function test_unlink_is_directory (line 549) | def test_unlink_is_directory(runner: CodeRunner) -> None:
function test_rmdir_not_found (line 574) | def test_rmdir_not_found(runner: CodeRunner) -> None:
function test_rmdir_not_a_directory (line 587) | def test_rmdir_not_a_directory(runner: CodeRunner) -> None:
function test_rmdir_not_empty (line 601) | def test_rmdir_not_empty(runner: CodeRunner) -> None:
function test_rename_source_not_found (line 620) | def test_rename_source_not_found(runner: CodeRunner) -> None:
function test_write_text_new_file (line 638) | def test_write_text_new_file(runner: CodeRunner) -> None:
function test_write_text_overwrite (line 647) | def test_write_text_overwrite(runner: CodeRunner) -> None:
function test_write_bytes_new_file (line 657) | def test_write_bytes_new_file(runner: CodeRunner) -> None:
function test_write_text_parent_not_found (line 666) | def test_write_text_parent_not_found(runner: CodeRunner) -> None:
function test_write_text_to_directory (line 679) | def test_write_text_to_directory(runner: CodeRunner) -> None:
function test_environ_key_access (line 698) | def test_environ_key_access(runner: CodeRunner) -> None:
function test_environ_get_method (line 705) | def test_environ_get_method(runner: CodeRunner) -> None:
function test_environ_get_missing_with_default (line 712) | def test_environ_get_missing_with_default(runner: CodeRunner) -> None:
function test_environ_missing_key_raises_keyerror (line 719) | def test_environ_missing_key_raises_keyerror(runner: CodeRunner) -> None:
FILE: crates/monty-python/tests/test_os_access_raw.py
class TestOS (line 16) | class TestOS(AbstractOS):
method __init__ (line 21) | def __init__(self) -> None:
method _ensure_parent_exists (line 25) | def _ensure_parent_exists(self, path: str) -> None:
method path_exists (line 32) | def path_exists(self, path: PurePosixPath) -> bool:
method path_is_file (line 36) | def path_is_file(self, path: PurePosixPath) -> bool:
method path_is_dir (line 39) | def path_is_dir(self, path: PurePosixPath) -> bool:
method path_is_symlink (line 42) | def path_is_symlink(self, path: PurePosixPath) -> bool:
method path_read_text (line 45) | def path_read_text(self, path: PurePosixPath) -> str:
method path_read_bytes (line 51) | def path_read_bytes(self, path: PurePosixPath) -> bytes:
method path_write_text (line 57) | def path_write_text(self, path: PurePosixPath, data: str) -> int:
method path_write_bytes (line 63) | def path_write_bytes(self, path: PurePosixPath, data: bytes) -> int:
method path_mkdir (line 69) | def path_mkdir(self, path: PurePosixPath, parents: bool, exist_ok: boo...
method path_unlink (line 79) | def path_unlink(self, path: PurePosixPath) -> None:
method path_rmdir (line 85) | def path_rmdir(self, path: PurePosixPath) -> None:
method path_iterdir (line 98) | def path_iterdir(self, path: PurePosixPath) -> list[PurePosixPath]:
method path_stat (line 122) | def path_stat(self, path: PurePosixPath) -> StatResult:
method path_rename (line 131) | def path_rename(self, path: PurePosixPath, target: PurePosixPath) -> N...
method path_resolve (line 149) | def path_resolve(self, path: PurePosixPath) -> str:
method path_absolute (line 161) | def path_absolute(self, path: PurePosixPath) -> str:
method getenv (line 167) | def getenv(self, key: str, default: str | None = None) -> str | None:
method get_environ (line 175) | def get_environ(self) -> dict[str, str]:
function test_abstract_filesystem_exists (line 187) | def test_abstract_filesystem_exists():
function test_abstract_filesystem_exists_missing (line 198) | def test_abstract_filesystem_exists_missing():
function test_abstract_filesystem_is_file (line 208) | def test_abstract_filesystem_is_file():
function test_abstract_filesystem_is_dir (line 224) | def test_abstract_filesystem_is_dir():
function test_abstract_filesystem_read_text (line 240) | def test_abstract_filesystem_read_text():
function test_abstract_filesystem_read_text_missing (line 251) | def test_abstract_filesystem_read_text_missing():
function test_abstract_filesystem_read_bytes (line 262) | def test_abstract_filesystem_read_bytes():
function test_abstract_filesystem_stat_file (line 278) | def test_abstract_filesystem_stat_file():
function test_abstract_filesystem_stat_directory (line 294) | def test_abstract_filesystem_stat_directory():
function test_abstract_filesystem_stat_missing (line 310) | def test_abstract_filesystem_stat_missing():
function test_abstract_filesystem_iterdir (line 333) | def test_abstract_filesystem_iterdir():
function test_abstract_filesystem_iterdir_empty (line 354) | def test_abstract_filesystem_iterdir_empty():
function test_abstract_filesystem_resolve (line 374) | def test_abstract_filesystem_resolve():
function test_abstract_filesystem_absolute (line 388) | def test_abstract_filesystem_absolute():
function test_abstract_filesystem_getenv (line 402) | def test_abstract_filesystem_getenv():
function test_abstract_filesystem_getenv_missing (line 416) | def test_abstract_filesystem_getenv_missing():
function test_abstract_filesystem_getenv_default (line 430) | def test_abstract_filesystem_getenv_default():
function test_file_stat_helper (line 449) | def test_file_stat_helper():
function test_dir_stat_helper (line 461) | def test_dir_stat_helper():
function test_path_monty_to_py (line 472) | def test_path_monty_to_py():
function test_path_py_to_monty (line 479) | def test_path_py_to_monty():
FILE: crates/monty-python/tests/test_os_calls.py
function test_path_exists_yields_oscall (line 22) | def test_path_exists_yields_oscall():
function test_path_stat_yields_oscall (line 34) | def test_path_stat_yields_oscall():
function test_path_read_text_yields_oscall (line 45) | def test_path_read_text_yields_oscall():
function test_path_concatenation (line 61) | def test_path_concatenation():
function test_exists_resume (line 81) | def test_exists_resume():
function test_read_text_resume (line 93) | def test_read_text_resume():
function test_stat_resume_and_use_in_monty (line 115) | def test_stat_resume_and_use_in_monty():
function test_stat_result_returned_from_monty (line 136) | def test_stat_result_returned_from_monty():
function test_stat_result (line 161) | def test_stat_result():
function test_multiple_path_calls (line 187) | def test_multiple_path_calls():
function test_conditional_path_calls (line 214) | def test_conditional_path_calls():
function test_os_call_vs_external_function (line 248) | def test_os_call_vs_external_function():
function test_os_basic (line 268) | def test_os_basic():
function test_os_stat (line 283) | def test_os_stat():
function test_os_multiple_calls (line 302) | def test_os_multiple_calls():
function test_os_not_provided_error (line 334) | def test_os_not_provided_error():
function test_os_not_provided_error_ext_func (line 348) | def test_os_not_provided_error_ext_func():
function test_not_callable (line 360) | def test_not_callable():
function test_os_getenv_yields_oscall (line 373) | def test_os_getenv_yields_oscall():
function test_os_getenv_with_default_yields_oscall (line 384) | def test_os_getenv_with_default_yields_oscall():
function test_os_getenv_callback (line 395) | def test_os_getenv_callback():
function test_os_getenv_callback_missing (line 410) | def test_os_getenv_callback_missing():
function test_os_getenv_callback_with_default (line 425) | def test_os_getenv_callback_with_default():
function test_os_environ_yields_oscall (line 445) | def test_os_environ_yields_oscall():
function test_os_environ_key_access (line 456) | def test_os_environ_key_access():
function test_os_environ_key_missing_raises (line 469) | def test_os_environ_key_missing_raises():
function test_os_environ_get_method (line 483) | def test_os_environ_get_method():
function test_os_environ_get_with_default (line 496) | def test_os_environ_get_with_default():
function test_os_environ_len (line 509) | def test_os_environ_len():
function test_os_environ_contains (line 522) | def test_os_environ_contains():
function test_os_environ_keys (line 535) | def test_os_environ_keys():
function test_os_environ_values (line 548) | def test_os_environ_values():
function test_path_write_text_yields_oscall (line 566) | def test_path_write_text_yields_oscall():
function test_path_write_text_resume (line 577) | def test_path_write_text_resume():
function test_path_write_text_callback (line 589) | def test_path_write_text_callback():
function test_path_write_bytes_yields_oscall (line 612) | def test_path_write_bytes_yields_oscall():
function test_path_write_bytes_resume (line 623) | def test_path_write_bytes_resume():
function test_path_mkdir_yields_oscall (line 640) | def test_path_mkdir_yields_oscall():
function test_path_mkdir_with_parents_yields_oscall (line 651) | def test_path_mkdir_with_parents_yields_oscall():
function test_path_mkdir_with_exist_ok_yields_oscall (line 663) | def test_path_mkdir_with_exist_ok_yields_oscall():
function test_path_mkdir_with_both_kwargs (line 674) | def test_path_mkdir_with_both_kwargs():
function test_path_mkdir_resume (line 683) | def test_path_mkdir_resume():
function test_path_unlink_yields_oscall (line 700) | def test_path_unlink_yields_oscall():
function test_path_unlink_resume (line 711) | def test_path_unlink_resume():
function test_path_rmdir_yields_oscall (line 728) | def test_path_rmdir_yields_oscall():
function test_path_rmdir_resume (line 739) | def test_path_rmdir_resume():
function test_path_rename_yields_oscall (line 756) | def test_path_rename_yields_oscall():
function test_path_rename_resume (line 767) | def test_path_rename_resume():
function test_write_operations_callback (line 785) | def test_write_operations_callback():
FILE: crates/monty-python/tests/test_print.py
function make_print_collector (line 11) | def make_print_collector() -> tuple[list[str], PrintCallback]:
function test_print_basic (line 22) | def test_print_basic() -> None:
function test_print_multiple (line 29) | def test_print_multiple() -> None:
function test_print_with_values (line 40) | def test_print_with_values() -> None:
function test_print_with_sep (line 47) | def test_print_with_sep() -> None:
function test_print_with_end (line 54) | def test_print_with_end() -> None:
function test_print_returns_none (line 61) | def test_print_returns_none() -> None:
function test_print_empty (line 68) | def test_print_empty() -> None:
function test_print_with_limits (line 75) | def test_print_with_limits() -> None:
function test_print_with_inputs (line 84) | def test_print_with_inputs() -> None:
function test_print_in_loop (line 92) | def test_print_in_loop() -> None:
function test_print_mixed_types (line 103) | def test_print_mixed_types() -> None:
function make_error_callback (line 110) | def make_error_callback(error: Exception) -> PrintCallback:
function test_print_callback_raises_value_error (line 119) | def test_print_callback_raises_value_error() -> None:
function test_print_callback_raises_type_error (line 130) | def test_print_callback_raises_type_error() -> None:
function test_print_callback_raises_in_function (line 141) | def test_print_callback_raises_in_function() -> None:
function test_print_callback_raises_in_nested_function (line 158) | def test_print_callback_raises_in_nested_function() -> None:
function test_print_callback_raises_in_loop (line 177) | def test_print_callback_raises_in_loop() -> None:
function test_map_print (line 200) | def test_map_print() -> None:
FILE: crates/monty-python/tests/test_re.py
function test_re_module (line 10) | def test_re_module():
function test_re_compile (line 16) | def test_re_compile():
function test_re_constant (line 41) | def test_re_constant(flags: list[str], target: int):
function test_re_compile_repr (line 48) | def test_re_compile_repr():
function test_re_match_repr (line 59) | def test_re_match_repr():
function test_re_match_groups (line 70) | def test_re_match_groups():
function test_re_substitution (line 82) | def test_re_substitution():
function test_re_error_handling (line 94) | def test_re_error_handling():
function test_re_resume (line 109) | def test_re_resume():
function test_re_persistence (line 132) | def test_re_persistence():
function test_re_error_upcast (line 154) | def test_re_error_upcast():
FILE: crates/monty-python/tests/test_readme_examples.py
function test_readme_examples (line 11) | def test_readme_examples(example: CodeExample, eval_example: EvalExample):
FILE: crates/monty-python/tests/test_repl.py
function make_print_collector (line 11) | def make_print_collector() -> tuple[list[str], PrintCallback]:
function test_default_construction (line 25) | def test_default_construction():
function test_custom_script_name (line 30) | def test_custom_script_name():
function test_repr (line 35) | def test_repr():
function test_feed_run_expression_returns_value (line 43) | def test_feed_run_expression_returns_value():
function test_feed_run_assignment_returns_none (line 48) | def test_feed_run_assignment_returns_none():
function test_feed_run_empty_string_returns_none (line 53) | def test_feed_run_empty_string_returns_none():
function test_feed_run_none_literal (line 58) | def test_feed_run_none_literal():
function test_variable_persists_across_feeds (line 66) | def test_variable_persists_across_feeds():
function test_incremental_mutation (line 72) | def test_incremental_mutation():
function test_multiple_variables (line 80) | def test_multiple_variables():
function test_function_defined_then_called (line 87) | def test_function_defined_then_called():
function test_function_uses_previously_defined_variable (line 93) | def test_function_uses_previously_defined_variable():
function test_list_mutation_persists (line 100) | def test_list_mutation_persists():
function test_dict_mutation_persists (line 108) | def test_dict_mutation_persists():
function test_variable_reassignment (line 116) | def test_variable_reassignment():
function test_multi_statement_snippet (line 127) | def test_multi_statement_snippet():
function test_loop_in_snippet (line 133) | def test_loop_in_snippet():
function test_if_else_in_snippet (line 139) | def test_if_else_in_snippet():
function test_feed_run_return_types (line 163) | def test_feed_run_return_types(code: str, expected: object):
function test_syntax_error (line 171) | def test_syntax_error():
function test_runtime_error_preserves_state (line 177) | def test_runtime_error_preserves_state():
function test_name_error (line 187) | def test_name_error():
function test_type_error (line 195) | def test_type_error():
function test_zero_division_error (line 203) | def test_zero_division_error():
function test_index_error (line 211) | def test_index_error():
function test_key_error (line 219) | def test_key_error():
function test_multiple_errors_dont_corrupt_state (line 227) | def test_multiple_errors_dont_corrupt_state():
function test_print_callback_on_feed (line 241) | def test_print_callback_on_feed():
function test_print_callback_across_feeds (line 248) | def test_print_callback_across_feeds():
function test_construction_with_limits (line 259) | def test_construction_with_limits():
function test_infinite_loop_with_limits (line 265) | def test_infinite_loop_with_limits():
function test_dump_load_roundtrip (line 275) | def test_dump_load_roundtrip():
function test_dump_load_preserves_functions (line 287) | def test_dump_load_preserves_functions():
function test_dump_load_preserves_script_name (line 295) | def test_dump_load_preserves_script_name():
function test_load_with_print_callback (line 301) | def test_load_with_print_callback():
function test_load_invalid_data (line 311) | def test_load_invalid_data():
function test_external_function_basic (line 319) | def test_external_function_basic():
function test_external_function_return_value (line 328) | def test_external_function_return_value():
function test_external_function_called_multiple_times (line 336) | def test_external_function_called_multiple_times():
function test_external_function_persists_state_across_feeds (line 351) | def test_external_function_persists_state_across_feeds():
function test_external_function_exception_becomes_runtime_error (line 360) | def test_external_function_exception_becomes_runtime_error():
function test_external_function_error_preserves_repl_state (line 373) | def test_external_function_error_preserves_repl_state():
function test_external_function_undefined_raises_name_error (line 386) | def test_external_function_undefined_raises_name_error():
function test_external_function_with_print_callback (line 396) | def test_external_function_with_print_callback():
function test_external_function_with_kwargs (line 404) | def test_external_function_with_kwargs():
function test_feed_run_no_externals_with_os_preserves_repl_state (line 413) | def test_feed_run_no_externals_with_os_preserves_repl_state():
function test_inputs_basic (line 436) | def test_inputs_basic():
function test_inputs_used_in_same_snippet (line 441) | def test_inputs_used_in_same_snippet():
function test_inputs_multiple_values (line 447) | def test_inputs_multiple_values():
function test_inputs_override_existing_variable (line 452) | def test_inputs_override_existing_variable():
function test_inputs_with_external_functions (line 458) | def test_inputs_with_external_functions():
function test_feed_start_no_external_calls (line 469) | def test_feed_start_no_external_calls():
function test_feed_start_state_persists (line 479) | def test_feed_start_state_persists():
function test_feed_start_external_function (line 488) | def test_feed_start_external_function():
function test_feed_start_external_function_preserves_state (line 502) | def test_feed_start_external_function_preserves_state():
function test_feed_start_multiple_external_calls (line 512) | def test_feed_start_multiple_external_calls():
function test_feed_start_error_preserves_repl_state (line 527) | def test_feed_start_error_preserves_repl_state():
function test_feed_start_resume_error_preserves_repl_state (line 537) | def test_feed_start_resume_error_preserves_repl_state():
function test_feed_start_with_inputs (line 549) | def test_feed_start_with_inputs():
function test_feed_start_with_print_callback (line 561) | def test_feed_start_with_print_callback():
function test_feed_start_name_lookup (line 574) | def test_feed_start_name_lookup():
function test_feed_start_dump_load_repl_snapshot (line 585) | def test_feed_start_dump_load_repl_snapshot():
function test_feed_start_dump_load_repl_snapshot_preserves_state (line 607) | def test_feed_start_dump_load_repl_snapshot_preserves_state():
function test_feed_start_dump_load_repl_snapshot_name_lookup (line 629) | def test_feed_start_dump_load_repl_snapshot_name_lookup():
function test_feed_start_dump_load_repl_snapshot_multiple_calls (line 646) | def test_feed_start_dump_load_repl_snapshot_multiple_calls():
function test_feed_start_dump_load_snapshot_errors_on_repl (line 673) | def test_feed_start_dump_load_snapshot_errors_on_repl():
function test_feed_start_dump_load_repl_snapshot_with_print_callback (line 685) | def test_feed_start_dump_load_repl_snapshot_with_print_callback():
function test_feed_start_dump_load_repl_snapshot_preserves_script_name (line 702) | def test_feed_start_dump_load_repl_snapshot_preserves_script_name():
function test_non_repl_dump_load_with_load_snapshot (line 714) | def test_non_repl_dump_load_with_load_snapshot():
function test_feed_start_dump_after_resume_fails (line 731) | def test_feed_start_dump_after_resume_fails():
function test_inputs_various_types (line 743) | def test_inputs_various_types():
FILE: crates/monty-python/tests/test_serialize.py
function test_monty_dump_load_roundtrip (line 10) | def test_monty_dump_load_roundtrip():
function test_monty_dump_load_preserves_script_name (line 21) | def test_monty_dump_load_preserves_script_name():
function test_monty_dump_load_preserves_inputs (line 29) | def test_monty_dump_load_preserves_inputs():
function test_monty_dump_load_preserves_external_functions (line 37) | def test_monty_dump_load_preserves_external_functions():
function test_monty_load_invalid_data (line 46) | def test_monty_load_invalid_data():
function test_progress_dump_load_roundtrip (line 52) | def test_progress_dump_load_roundtrip():
function test_progress_dump_load_preserves_script_name (line 72) | def test_progress_dump_load_preserves_script_name():
function test_progress_dump_load_with_kwargs (line 83) | def test_progress_dump_load_with_kwargs():
function test_progress_dump_after_resume_fails (line 96) | def test_progress_dump_after_resume_fails():
function test_progress_load_invalid_data (line 108) | def test_progress_load_invalid_data():
function test_progress_dump_load_multiple_calls (line 113) | def test_progress_dump_load_multiple_calls():
function test_progress_load_with_print_callback (line 142) | def test_progress_load_with_print_callback():
function test_progress_load_without_print_callback (line 164) | def test_progress_load_without_print_callback():
function test_monty_dump_load_various_outputs (line 189) | def test_monty_dump_load_various_outputs(code: str, expected: Any):
function test_progress_dump_load_with_limits (line 196) | def test_progress_dump_load_with_limits():
class Person (line 212) | class Person:
function test_monty_load_dataclass (line 217) | def test_monty_load_dataclass():
function test_progress_dump_load_dataclass (line 227) | def test_progress_dump_load_dataclass():
function test_progress_dump_load_unknown_dataclass (line 249) | def test_progress_dump_load_unknown_dataclass():
FILE: crates/monty-python/tests/test_start.py
function test_start_no_external_functions_returns_complete (line 9) | def test_start_no_external_functions_returns_complete():
function test_start_with_external_function_returns_progress (line 16) | def test_start_with_external_function_returns_progress():
function test_start_custom_script_name (line 26) | def test_start_custom_script_name():
function test_start_progress_resume_returns_complete (line 33) | def test_start_progress_resume_returns_complete():
function test_start_progress_with_args (line 46) | def test_start_progress_with_args():
function test_start_progress_with_kwargs (line 55) | def test_start_progress_with_kwargs():
function test_start_progress_with_mixed_args_kwargs (line 64) | def test_start_progress_with_mixed_args_kwargs():
function test_start_multiple_external_calls (line 73) | def test_start_multiple_external_calls():
function test_start_chain_of_external_calls (line 92) | def test_start_chain_of_external_calls():
function test_start_with_inputs (line 109) | def test_start_with_inputs():
function test_start_with_limits (line 117) | def test_start_with_limits():
function test_start_with_print_callback (line 125) | def test_start_with_print_callback():
function test_start_resume_cannot_be_called_twice (line 137) | def test_start_resume_cannot_be_called_twice():
function test_start_complex_return_value (line 151) | def test_start_complex_return_value():
function test_start_resume_with_none (line 161) | def test_start_resume_with_none():
function test_progress_repr (line 171) | def test_progress_repr():
function test_complete_repr (line 180) | def test_complete_repr():
function test_start_can_reuse_monty_instance (line 187) | def test_start_can_reuse_monty_instance():
function test_start_returns_complete_for_various_types (line 218) | def test_start_returns_complete_for_various_types(code: str, expected: A...
function test_start_progress_resume_with_exception_caught (line 225) | def test_start_progress_resume_with_exception_caught():
function test_start_progress_resume_exception_propagates_uncaught (line 244) | def test_start_progress_resume_exception_propagates_uncaught():
function test_resume_none (line 259) | def test_resume_none():
function test_invalid_resume_args (line 269) | def test_invalid_resume_args():
function test_start_progress_resume_exception_in_nested_try (line 292) | def test_start_progress_resume_exception_in_nested_try():
function test_name_lookup (line 317) | def test_name_lookup():
function test_ext_function_alt_name (line 326) | def test_ext_function_alt_name():
FILE: crates/monty-python/tests/test_threading.py
function test_parallel_exec (line 18) | def test_parallel_exec():
function test_parallel_exec_print (line 44) | def test_parallel_exec_print():
function double (line 76) | def double(a: int) -> int:
function test_parallel_exec_ext_functions (line 80) | def test_parallel_exec_ext_functions():
function test_parallel_exec_start (line 109) | def test_parallel_exec_start():
function test_parallel_exec_start_resume (line 135) | def test_parallel_exec_start_resume():
FILE: crates/monty-python/tests/test_type_check.py
function test_type_check_no_errors (line 7) | def test_type_check_no_errors():
function test_type_check_with_errors (line 13) | def test_type_check_with_errors():
function test_type_check_function_return_type (line 33) | def test_type_check_function_return_type():
function test_type_check_undefined_variable (line 56) | def test_type_check_undefined_variable():
function test_type_check_valid_function (line 73) | def test_type_check_valid_function():
function test_type_check_with_prefix_code (line 85) | def test_type_check_with_prefix_code():
function test_type_check_display_invalid_format (line 95) | def test_type_check_display_invalid_format():
function test_type_check_display_concise_format (line 105) | def test_type_check_display_concise_format():
function test_monty_typing_error_is_monty_error_subclass (line 118) | def test_monty_typing_error_is_monty_error_subclass():
function test_monty_typing_error_repr (line 128) | def test_monty_typing_error_repr():
function test_monty_typing_error_caught_as_monty_error (line 150) | def test_monty_typing_error_caught_as_monty_error():
function test_monty_typing_error_display_default (line 157) | def test_monty_typing_error_display_default():
function test_constructor_type_check_default_false (line 169) | def test_constructor_type_check_default_false():
function test_constructor_type_check_explicit_true (line 178) | def test_constructor_type_check_explicit_true():
function test_constructor_type_check_explicit_false (line 197) | def test_constructor_type_check_explicit_false():
function test_constructor_default_allows_run_with_inputs (line 206) | def test_constructor_default_allows_run_with_inputs():
function test_constructor_type_check_stubs (line 215) | def test_constructor_type_check_stubs():
function test_constructor_type_check_stubs_with_external_function (line 224) | def test_constructor_type_check_stubs_with_external_function():
function test_constructor_type_check_stubs_invalid (line 239) | def test_constructor_type_check_stubs_invalid():
function test_inject_stubs_offset (line 264) | def test_inject_stubs_offset():
FILE: crates/monty-python/tests/test_types.py
function test_none_input (line 7) | def test_none_input():
function test_none_output (line 12) | def test_none_output():
function test_bool_true (line 17) | def test_bool_true():
function test_bool_false (line 24) | def test_bool_false():
function test_int (line 31) | def test_int():
function test_float (line 38) | def test_float():
function test_string (line 45) | def test_string():
function test_bytes (line 52) | def test_bytes():
function test_list (line 59) | def test_list():
function test_tuple (line 66) | def test_tuple():
function test_dict (line 73) | def test_dict():
function test_set (line 79) | def test_set():
function test_frozenset (line 85) | def test_frozenset():
function test_ellipsis_input (line 91) | def test_ellipsis_input():
function test_ellipsis_output (line 96) | def test_ellipsis_output():
function test_nested_list (line 101) | def test_nested_list():
function test_nested_dict (line 107) | def test_nested_dict():
function test_mixed_nested (line 113) | def test_mixed_nested():
function test_list_output (line 122) | def test_list_output():
function test_dict_output (line 127) | def test_dict_output():
function test_tuple_output (line 132) | def test_tuple_output():
function test_set_output (line 137) | def test_set_output():
function test_exception_input (line 145) | def test_exception_input():
function test_exception_output (line 153) | def test_exception_output():
function test_exception_roundtrip (line 161) | def test_exception_roundtrip(exc_class: type[Exception]):
function test_exception_subclass_input (line 169) | def test_exception_subclass_input():
function test_int_subclass_input (line 188) | def test_int_subclass_input():
function test_str_subclass_input (line 198) | def test_str_subclass_input():
function test_list_subclass_input (line 208) | def test_list_subclass_input():
function test_dict_subclass_input (line 218) | def test_dict_subclass_input():
function test_tuple_subclass_input (line 228) | def test_tuple_subclass_input():
function test_set_subclass_input (line 238) | def test_set_subclass_input():
function test_bool_preserves_type (line 248) | def test_bool_preserves_type():
function test_return_int (line 256) | def test_return_int():
function test_return_exception (line 266) | def test_return_exception():
function test_return_builtin (line 276) | def test_return_builtin():
function test_bigint_input (line 285) | def test_bigint_input():
function test_bigint_output (line 294) | def test_bigint_output():
function test_bigint_negative_input (line 302) | def test_bigint_negative_input():
function test_int_overflow_to_bigint (line 311) | def test_int_overflow_to_bigint():
function test_bigint_arithmetic (line 320) | def test_bigint_arithmetic():
function test_bigint_comparison (line 329) | def test_bigint_comparison():
function test_bigint_in_collection (line 337) | def test_bigint_in_collection():
function test_bigint_as_dict_key (line 346) | def test_bigint_as_dict_key():
function test_bigint_hash_consistency_small_values (line 355) | def test_bigint_hash_consistency_small_values():
function test_bigint_hash_consistency_boundary (line 377) | def test_bigint_hash_consistency_boundary():
function test_bigint_hash_consistency_large_values (line 388) | def test_bigint_hash_consistency_large_values():
function test_namedtuple_sys_version_info (line 411) | def test_namedtuple_sys_version_info():
function test_namedtuple_sys_version_info_index_access (line 431) | def test_namedtuple_sys_version_info_index_access():
function test_namedtuple_sys_version_info_tuple_comparison (line 442) | def test_namedtuple_sys_version_info_tuple_comparison():
function test_namedtuple_custom_input_attribute_access (line 452) | def test_namedtuple_custom_input_attribute_access():
function test_namedtuple_custom_input_index_access (line 467) | def test_namedtuple_custom_input_index_access():
function test_namedtuple_custom_input_multiple_fields (line 479) | def test_namedtuple_custom_input_multiple_fields():
function test_namedtuple_custom_input_repr (line 498) | def test_namedtuple_custom_input_repr():
function test_namedtuple_custom_input_len (line 512) | def test_namedtuple_custom_input_len():
function test_namedtuple_custom_input_roundtrip (line 525) | def test_namedtuple_custom_input_roundtrip():
function test_namedtuple_custom_missing_attr_error (line 542) | def test_namedtuple_custom_missing_attr_error():
FILE: crates/monty-type-checking/src/db.rs
type MemoryDb (line 22) | pub(crate) struct MemoryDb {
method fmt (line 32) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method new (line 44) | pub fn new() -> Self {
method test_system (line 57) | fn test_system(&self) -> &TestSystem {
method test_system_mut (line 61) | fn test_system_mut(&mut self) -> &mut TestSystem {
method vendored (line 68) | fn vendored(&self) -> &VendoredFileSystem {
method system (line 72) | fn system(&self) -> &dyn System {
method files (line 76) | fn files(&self) -> &Files {
method python_version (line 80) | fn python_version(&self) -> PythonVersion {
method should_check_file (line 87) | fn should_check_file(&self, file: File) -> bool {
method rule_selection (line 91) | fn rule_selection(&self, _file: File) -> &RuleSelection {
method lint_registry (line 95) | fn lint_registry(&self) -> &LintRegistry {
method analysis_settings (line 99) | fn analysis_settings(&self, _file: File) -> &AnalysisSettings {
method verbose (line 103) | fn verbose(&self) -> bool {
method search_paths (line 110) | fn search_paths(&self) -> &SearchPaths {
FILE: crates/monty-type-checking/src/type_check.rs
type SourceFile (line 24) | pub struct SourceFile<'a> {
function new (line 34) | pub fn new(source_code: &'a str, path: &'a str) -> Self {
function type_check (line 49) | pub fn type_check(
function to_string (line 143) | fn to_string(err: impl Display) -> String {
function adjust_annotation_span (line 152) | fn adjust_annotation_span(ann: &mut Annotation, main_file: File, offset:...
type TypeCheckingDiagnostics (line 167) | pub struct TypeCheckingDiagnostics {
method fmt (line 182) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 204) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method new (line 211) | fn new(diagnostics: Vec<Diagnostic>, db: MemoryDb) -> Self {
method config (line 220) | fn config(&self) -> DisplayDiagnosticConfig {
method debug_details (line 228) | pub fn debug_details(&self) -> DebugTypeCheckingDiagnostics<'_> {
method format (line 239) | pub fn format(self, format: DiagnosticFormat) -> Self {
method format_from_str (line 246) | pub fn format_from_str(self, format: &str) -> Result<Self, String> {
method color (line 266) | pub fn color(self, color: bool) -> Self {
type DebugTypeCheckingDiagnostics (line 196) | pub struct DebugTypeCheckingDiagnostics<'a> {
function filter_diagnostics (line 274) | fn filter_diagnostics(d: &Diagnostic) -> bool {
FILE: crates/monty-type-checking/tests/bad_types.py
function takes_int (line 9) | def takes_int(x: int) -> None:
function takes_str (line 13) | def takes_str(x: str) -> None:
function takes_list_int (line 17) | def takes_list_int(x: list[int]) -> None:
function should_return_int (line 35) | def should_return_int() -> int:
function should_return_str (line 39) | def should_return_str() -> str:
function should_return_list_int (line 43) | def should_return_list_int() -> list[int]:
function should_return_none (line 47) | def should_return_none() -> None:
function get_int (line 54) | def get_int() -> int:
function get_str (line 58) | def get_str() -> str:
class MyClass (line 79) | class MyClass:
method __init__ (line 80) | def __init__(self) -> None:
function takes_two (line 91) | def takes_two(a: int, b: str) -> None:
FILE: crates/monty-type-checking/tests/good_types.py
function check_int (line 12) | def check_int(x: int) -> None:
function check_float (line 16) | def check_float(x: float) -> None:
function check_str (line 20) | def check_str(x: str) -> None:
function check_bool (line 24) | def check_bool(x: bool) -> None:
function check_bytes (line 28) | def check_bytes(x: bytes) -> None:
function check_list_int (line 32) | def check_list_int(x: list[int]) -> None:
function check_list_str (line 36) | def check_list_str(x: list[str]) -> None:
function check_tuple_int (line 40) | def check_tuple_int(x: tuple[int, ...]) -> None:
function check_dict_str_int (line 44) | def check_dict_str_int(x: dict[str, int]) -> None:
function check_set_int (line 48) | def check_set_int(x: set[int]) -> None:
function check_frozenset_int (line 52) | def check_frozenset_int(x: frozenset[int]) -> None:
function get_int (line 59) | def get_int() -> int:
function get_float (line 63) | def get_float() -> float:
function get_str (line 67) | def get_str() -> str:
function get_list_int (line 71) | def get_list_int() -> list[int]:
function get_list_str (line 75) | def get_list_str() -> list[str]:
function get_object (line 79) | def get_object() -> object:
function get_dict_str_int (line 83) | def get_dict_str_int() -> dict[str, int]:
function get_set_str (line 87) | def get_set_str() -> set[str]:
function get_frozenset_str (line 91) | def get_frozenset_str() -> frozenset[str]:
function get_tuple_str_int (line 95) | def get_tuple_str_int() -> tuple[str, int]:
function get_bytes (line 99) | def get_bytes() -> bytes:
function handle_base (line 324) | def handle_base(e: BaseException) -> None:
function handle_exception (line 334) | def handle_exception(e: Exception) -> None:
function may_fail (line 366) | def may_fail(x_fail: int) -> int:
function not_implemented (line 374) | def not_implemented() -> None:
function foo (line 386) | async def foo(a: int):
function bar (line 390) | async def bar():
class Point (line 402) | class Point:
FILE: crates/monty-type-checking/tests/main.rs
function type_checking_success (line 8) | fn type_checking_success() {
function type_checking_error (line 21) | fn type_checking_error() {
function type_checking_error_stubs (line 57) | fn type_checking_error_stubs() {
function type_checking_error_concise (line 103) | fn type_checking_error_concise() {
function missing_stdlib_datetime (line 125) | fn missing_stdlib_datetime() {
function type_good_types (line 145) | fn type_good_types() {
function check_file_content (line 151) | fn check_file_content(file_name: &str, mut actual: &str) {
function type_bad_types (line 182) | fn type_bad_types() {
function test_reveal_types (line 195) | fn test_reveal_types() {
FILE: crates/monty-typeshed/build.rs
constant TYPESHED_SOURCE_DIR (line 18) | const TYPESHED_SOURCE_DIR: &str = "vendor/typeshed";
constant TYPESHED_ZIP_LOCATION (line 20) | const TYPESHED_ZIP_LOCATION: &str = "/zipped_typeshed.zip";
function write_zipped_typeshed_to (line 27) | fn write_zipped_typeshed_to(writer: File) -> ZipResult<File> {
function main (line 87) | fn main() {
FILE: crates/monty-typeshed/custom/asyncio.pyi
class _Future (line 12) | class _Future(Awaitable[_T]):
method __iter__ (line 16) | def __iter__(self) -> Generator[Any, None, _T]: ...
method __await__ (line 17) | def __await__(self) -> Generator[Any, None, _T]: ...
function run (line 21) | def run(main: Awaitable[_T], *, debug: bool | None = None, loop_factory:...
function gather (line 23) | def gather(
function gather (line 27) | def gather(
function gather (line 35) | def gather(
function gather (line 44) | def gather(
function gather (line 54) | def gather(
function gather (line 65) | def gather(
function gather (line 77) | def gather(*coros_or_futures: _FutureLike[_T], return_exceptions: Litera...
function gather (line 79) | def gather(coro_or_future1: _FutureLike[_T1], /, *, return_exceptions: b...
function gather (line 81) | def gather(
function gather (line 85) | def gather(
function gather (line 94) | def gather(
function gather (line 104) | def gather(
function gather (line 117) | def gather(
function gather (line 138) | def gather(*coros_or_futures: _FutureLike[_T], return_exceptions: bool) ...
FILE: crates/monty-typeshed/custom/os.pyi
function getenv (line 10) | def getenv(key: str) -> str | None: ...
function getenv (line 12) | def getenv(key: str, default: _T) -> str | _T: ...
class stat_result (line 14) | class stat_result(structseq[float], tuple[int, int, int, int, int, int, ...
method st_mode (line 27) | def st_mode(self) -> int:
method st_ino (line 32) | def st_ino(self) -> int:
method st_dev (line 37) | def st_dev(self) -> int:
method st_nlink (line 42) | def st_nlink(self) -> int:
method st_uid (line 47) | def st_uid(self) -> int:
method st_gid (line 52) | def st_gid(self) -> int:
method st_size (line 57) | def st_size(self) -> int:
method st_atime (line 62) | def st_atime(self) -> float:
method st_mtime (line 67) | def st_mtime(self) -> float:
method st_ctime (line 72) | def st_ctime(self) -> float:
class PathLike (line 82) | class PathLike(ABC, Protocol[AnyStr_co]): # type: ignore[misc] # pyrig...
method __fspath__ (line 85) | def __fspath__(self) -> AnyStr_co: ...
FILE: crates/monty-typeshed/custom/sys.pyi
class _version_info (line 19) | class _version_info(_UninstantiableStructseq, tuple[int, int, int, _Rele...
method major (line 23) | def major(self) -> int: ...
method minor (line 25) | def minor(self) -> int: ...
method micro (line 27) | def micro(self) -> int: ...
method releaselevel (line 29) | def releaselevel(self) -> _ReleaseLevel: ...
method serial (line 31) | def serial(self) -> int: ...
FILE: crates/monty-typeshed/src/lib.rs
constant SOURCE_COMMIT (line 6) | pub const SOURCE_COMMIT: &str = include_str!("../vendor/typeshed/source_...
function file_system (line 13) | pub fn file_system() -> &'static VendoredFileSystem {
function test_commit (line 26) | fn test_commit() {
function typeshed_zip_created_at_build_time (line 31) | fn typeshed_zip_created_at_build_time() {
function typeshed_versions_file_exists (line 44) | fn typeshed_versions_file_exists() {
FILE: crates/monty-typeshed/update.py
function clone_or_update_typeshed (line 160) | def clone_or_update_typeshed() -> str:
function filter_statements (line 189) | def filter_statements(nodes: list[ast.stmt]) -> list[ast.stmt]:
function filter_if_block (line 223) | def filter_if_block(node: ast.If) -> ast.If | None:
function filter_builtins (line 250) | def filter_builtins(source: str) -> str:
function main (line 269) | def main() -> int:
FILE: crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi
class dict_keys (line 72) | class dict_keys(KeysView[_KT_co], Generic[_KT_co, _VT_co]): # undocumented
method __eq__ (line 73) | def __eq__(self, value: object, /) -> bool: ...
method __reversed__ (line 74) | def __reversed__(self) -> Iterator[_KT_co]: ...
method isdisjoint (line 77) | def isdisjoint(self, other: Iterable[_KT_co], /) -> bool: ...
method mapping (line 80) | def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ...
class dict_values (line 83) | class dict_values(ValuesView[_VT_co], Generic[_KT_co, _VT_co]): # undoc...
method __reversed__ (line 84) | def __reversed__(self) -> Iterator[_VT_co]: ...
method mapping (line 87) | def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ...
class dict_items (line 90) | class dict_items(ItemsView[_KT_co, _VT_co]): # undocumented
method __eq__ (line 91) | def __eq__(self, value: object, /) -> bool: ...
method __reversed__ (line 92) | def __reversed__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ...
method isdisjoint (line 95) | def isdisjoint(self, other: Iterable[tuple[_KT_co, _VT_co]], /) -> boo...
method mapping (line 98) | def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ...
class Buffer (line 102) | class Buffer(Protocol):
method __buffer__ (line 105) | def __buffer__(self, flags: int, /) -> memoryview: ...
FILE: crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi
class IdentityFunction (line 76) | class IdentityFunction(Protocol):
method __call__ (line 77) | def __call__(self, x: _T, /) -> _T: ...
class SupportsNext (line 80) | class SupportsNext(Protocol[_T_co]):
method __next__ (line 81) | def __next__(self) -> _T_co: ...
class SupportsAnext (line 84) | class SupportsAnext(Protocol[_T_co]):
method __anext__ (line 85) | def __anext__(self) -> Awaitable[_T_co]: ...
class SupportsBool (line 87) | class SupportsBool(Protocol):
method __bool__ (line 88) | def __bool__(self) -> bool: ...
class SupportsDunderLT (line 91) | class SupportsDunderLT(Protocol[_T_contra]):
method __lt__ (line 92) | def __lt__(self, other: _T_contra, /) -> SupportsBool: ...
class SupportsDunderGT (line 94) | class SupportsDunderGT(Protocol[_T_contra]):
method __gt__ (line 95) | def __gt__(self, other: _T_contra, /) -> SupportsBool: ...
class SupportsDunderLE (line 97) | class SupportsDunderLE(Protocol[_T_contra]):
method __le__ (line 98) | def __le__(self, other: _T_contra, /) -> SupportsBool: ...
class SupportsDunderGE (line 100) | class SupportsDunderGE(Protocol[_T_contra]):
method __ge__ (line 101) | def __ge__(self, other: _T_contra, /) -> SupportsBool: ...
class SupportsAllComparisons (line 103) | class SupportsAllComparisons(
class SupportsAdd (line 112) | class SupportsAdd(Protocol[_T_contra, _T_co]):
method __add__ (line 113) | def __add__(self, x: _T_contra, /) -> _T_co: ...
class SupportsRAdd (line 115) | class SupportsRAdd(Protocol[_T_contra, _T_co]):
method __radd__ (line 116) | def __radd__(self, x: _T_contra, /) -> _T_co: ...
class SupportsSub (line 118) | class SupportsSub(Protocol[_T_contra, _T_co]):
method __sub__ (line 119) | def __sub__(self, x: _T_contra, /) -> _T_co: ...
class SupportsRSub (line 121) | class SupportsRSub(Protocol[_T_contra, _T_co]):
method __rsub__ (line 122) | def __rsub__(self, x: _T_contra, /) -> _T_co: ...
class SupportsMul (line 124) | class SupportsMul(Protocol[_T_contra, _T_co]):
method __mul__ (line 125) | def __mul__(self, x: _T_contra, /) -> _T_co: ...
class SupportsRMul (line 127) | class SupportsRMul(Protocol[_T_contra, _T_co]):
method __rmul__ (line 128) | def __rmul__(self, x: _T_contra, /) -> _T_co: ...
class SupportsDivMod (line 130) | class SupportsDivMod(Protocol[_T_contra, _T_co]):
method __divmod__ (line 131) | def __divmod__(self, other: _T_contra, /) -> _T_co: ...
class SupportsRDivMod (line 133) | class SupportsRDivMod(Protocol[_T_contra, _T_co]):
method __rdivmod__ (line 134) | def __rdivmod__(self, other: _T_contra, /) -> _T_co: ...
class SupportsIter (line 138) | class SupportsIter(Protocol[_T_co]):
method __iter__ (line 139) | def __iter__(self) -> _T_co: ...
class SupportsAiter (line 143) | class SupportsAiter(Protocol[_T_co]):
method __aiter__ (line 144) | def __aiter__(self) -> _T_co: ...
class SupportsLen (line 146) | class SupportsLen(Protocol):
method __len__ (line 147) | def __len__(self) -> int: ...
class SupportsLenAndGetItem (line 149) | class SupportsLenAndGetItem(Protocol[_T_co]):
method __len__ (line 150) | def __len__(self) -> int: ...
method __getitem__ (line 151) | def __getitem__(self, k: int, /) -> _T_co: ...
class SupportsTrunc (line 153) | class SupportsTrunc(Protocol):
method __trunc__ (line 154) | def __trunc__(self) -> int: ...
class SupportsItems (line 159) | class SupportsItems(Protocol[_KT_co, _VT_co]):
method items (line 160) | def items(self) -> AbstractSet[tuple[_KT_co, _VT_co]]: ...
class SupportsKeysAndGetItem (line 163) | class SupportsKeysAndGetItem(Protocol[_KT, _VT_co]):
method keys (line 164) | def keys(self) -> Iterable[_KT]: ...
method __getitem__ (line 165) | def __getitem__(self, key: _KT, /) -> _VT_co: ...
class SupportsGetItem (line 168) | class SupportsGetItem(Protocol[_KT_contra, _VT_co]):
method __getitem__ (line 169) | def __getitem__(self, key: _KT_contra, /) -> _VT_co: ...
class SupportsContainsAndGetItem (line 172) | class SupportsContainsAndGetItem(Protocol[_KT_contra, _VT_co]):
method __contains__ (line 173) | def __contains__(self, x: Any, /) -> bool: ...
method __getitem__ (line 174) | def __getitem__(self, key: _KT_contra, /) -> _VT_co: ...
class SupportsItemAccess (line 177) | class SupportsItemAccess(Protocol[_KT_contra, _VT]):
method __contains__ (line 178) | def __contains__(self, x: Any, /) -> bool: ...
method __getitem__ (line 179) | def __getitem__(self, key: _KT_contra, /) -> _VT: ...
method __setitem__ (line 180) | def __setitem__(self, key: _KT_contra, value: _VT, /) -> None: ...
method __delitem__ (line 181) | def __delitem__(self, key: _KT_contra, /) -> None: ...
class HasFileno (line 256) | class HasFileno(Protocol):
method fileno (line 257) | def fileno(self) -> int: ...
class SupportsRead (line 264) | class SupportsRead(Protocol[_T_co]):
method read (line 265) | def read(self, length: int = ..., /) -> _T_co: ...
class SupportsReadline (line 268) | class SupportsReadline(Protocol[_T_co]):
method readline (line 269) | def readline(self, length: int = ..., /) -> _T_co: ...
class SupportsNoArgReadline (line 272) | class SupportsNoArgReadline(Protocol[_T_co]):
method readline (line 273) | def readline(self) -> _T_co: ...
class SupportsWrite (line 276) | class SupportsWrite(Protocol[_T_contra]):
method write (line 277) | def write(self, s: _T_contra, /) -> object: ...
class SupportsFlush (line 280) | class SupportsFlush(Protocol):
method flush (line 281) | def flush(self) -> object: ...
class Viewable (line 284) | class Viewable(Protocol[_T_co]):
method __len__ (line 285) | def __len__(self) -> int: ...
method __iter__ (line 286) | def __iter__(self) -> Iterator[_T_co]: ...
class SupportsGetItemViewable (line 288) | class SupportsGetItemViewable(Protocol[_KT, _VT_co]):
method __len__ (line 289) | def __len__(self) -> int: ...
method __iter__ (line 290) | def __iter__(self) -> Iterator[_KT]: ...
method __getitem__ (line 291) | def __getitem__(self, key: _KT, /) -> _VT_co: ...
class SliceableBuffer (line 303) | class SliceableBuffer(Buffer, Protocol):
method __getitem__ (line 304) | def __getitem__(self, slice: slice[SupportsIndex | None], /) -> Sequen...
class IndexableBuffer (line 306) | class IndexableBuffer(Buffer, Protocol):
method __getitem__ (line 307) | def __getitem__(self, i: int, /) -> int: ...
class SupportsGetItemBuffer (line 309) | class SupportsGetItemBuffer(SliceableBuffer, IndexableBuffer, Protocol):
method __contains__ (line 310) | def __contains__(self, x: Any, /) -> bool: ...
method __getitem__ (line 312) | def __getitem__(self, slice: slice[SupportsIndex | None], /) -> Sequen...
method __getitem__ (line 314) | def __getitem__(self, i: int, /) -> int: ...
class SizedBuffer (line 316) | class SizedBuffer(Sized, Buffer, Protocol): ...
class NoneType (line 327) | class NoneType:
method __bool__ (line 328) | def __bool__(self) -> Literal[False]: ...
class structseq (line 335) | class structseq(Generic[_T_co]):
method __new__ (line 345) | def __new__(cls, sequence: Iterable[_T_co], dict: dict[str, Any] = ......
method __replace__ (line 347) | def __replace__(self, **kwargs: Any) -> _Self: ...
class DataclassInstance (line 366) | class DataclassInstance(Protocol):
class StrEnum (line 383) | class StrEnum(str, Enum): ...
FILE: crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi
class _Future (line 12) | class _Future(Awaitable[_T]):
method __iter__ (line 16) | def __iter__(self) -> Generator[Any, None, _T]: ...
method __await__ (line 17) | def __await__(self) -> Generator[Any, None, _T]: ...
function run (line 21) | def run(main: Awaitable[_T], *, debug: bool | None = None, loop_factory:...
function gather (line 23) | def gather(
function gather (line 27) | def gather(
function gather (line 35) | def gather(
function gather (line 44) | def gather(
function gather (line 54) | def gather(
function gather (line 65) | def gather(
function gather (line 77) | def gather(*coros_or_futures: _FutureLike[_T], return_exceptions: Litera...
function gather (line 79) | def gather(coro_or_future1: _FutureLike[_T1], /, *, return_exceptions: b...
function gather (line 81) | def gather(
function gather (line 85) | def gather(
function gather (line 94) | def gather(
function gather (line 104) | def gather(
function gather (line 117) | def gather(
function gather (line 138) | def gather(*coros_or_futures: _FutureLike[_T], return_exceptions: bool) ...
FILE: crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi
class object (line 81) | class object:
method __class__ (line 88) | def __class__(self) -> type[Self]: ...
method __class__ (line 90) | def __class__(self, type: type[Self], /) -> None: ...
method __init__ (line 91) | def __init__(self) -> None: ...
method __new__ (line 92) | def __new__(cls) -> Self: ...
method __setattr__ (line 93) | def __setattr__(self, name: str, value: Any, /) -> None: ...
method __delattr__ (line 94) | def __delattr__(self, name: str, /) -> None: ...
method __eq__ (line 95) | def __eq__(self, value: object, /) -> bool: ...
method __ne__ (line 96) | def __ne__(self, value: object, /) -> bool: ...
method __str__ (line 97) | def __str__(self) -> str: ...
method __repr__ (line 98) | def __repr__(self) -> str: ...
method __hash__ (line 99) | def __hash__(self) -> int: ...
method __format__ (line 100) | def __format__(self, format_spec: str, /) -> str: ...
method __getattribute__ (line 101) | def __getattribute__(self, name: str, /) -> Any: ...
method __sizeof__ (line 102) | def __sizeof__(self) -> int: ...
method __reduce__ (line 103) | def __reduce__(self) -> str | tuple[Any, ...]: ...
method __reduce_ex__ (line 104) | def __reduce_ex__(self, protocol: SupportsIndex, /) -> str | tuple[Any...
method __getstate__ (line 106) | def __getstate__(self) -> object: ...
method __dir__ (line 108) | def __dir__(self) -> Iterable[str]: ...
method __init_subclass__ (line 109) | def __init_subclass__(cls) -> None: ...
method __subclasshook__ (line 111) | def __subclasshook__(cls, subclass: type, /) -> bool: ...
class type (line 114) | class type:
method __base__ (line 116) | def __base__(self) -> type | None: ...
method __basicsize__ (line 120) | def __basicsize__(self) -> int: ...
method __dictoffset__ (line 124) | def __dictoffset__(self) -> int: ...
method __flags__ (line 126) | def __flags__(self) -> int: ...
method __itemsize__ (line 128) | def __itemsize__(self) -> int: ...
method __mro__ (line 132) | def __mro__(self) -> tuple[type, ...]: ...
method __text_signature__ (line 137) | def __text_signature__(self) -> str | None: ...
method __weakrefoffset__ (line 139) | def __weakrefoffset__(self) -> int: ...
method __init__ (line 141) | def __init__(self, o: object, /) -> None: ...
method __init__ (line 143) | def __init__(self, name: str, bases: tuple[type, ...], dict: dict[str,...
method __new__ (line 145) | def __new__(cls, o: object, /) -> type: ...
method __new__ (line 147) | def __new__(
method __call__ (line 150) | def __call__(self, *args: Any, **kwds: Any) -> Any: ...
method __subclasses__ (line 151) | def __subclasses__(self: _typeshed.Self) -> list[_typeshed.Self]: ...
method mro (line 152) | def mro(self) -> list[type]: ...
method __instancecheck__ (line 153) | def __instancecheck__(self, instance: Any, /) -> bool: ...
method __subclasscheck__ (line 154) | def __subclasscheck__(self, subclass: type, /) -> bool: ...
method __prepare__ (line 156) | def __prepare__(metacls, name: str, bases: tuple[type, ...], /, **kwds...
method __or__ (line 158) | def __or__(self: _typeshed.Self, value: Any, /) -> types.UnionType | _...
method __ror__ (line 159) | def __ror__(self: _typeshed.Self, value: Any, /) -> types.UnionType | ...
class int (line 175) | class int:
method __new__ (line 177) | def __new__(cls, x: ConvertibleToInt = 0, /) -> Self: ...
method __new__ (line 179) | def __new__(cls, x: str | bytes | bytearray, /, base: SupportsIndex) -...
method as_integer_ratio (line 180) | def as_integer_ratio(self) -> tuple[int, Literal[1]]: ...
method real (line 182) | def real(self) -> int: ...
method imag (line 184) | def imag(self) -> Literal[0]: ...
method numerator (line 186) | def numerator(self) -> int: ...
method denominator (line 188) | def denominator(self) -> Literal[1]: ...
method conjugate (line 189) | def conjugate(self) -> int: ...
method bit_length (line 190) | def bit_length(self) -> int: ...
method bit_count (line 192) | def bit_count(self) -> int: ...
method to_bytes (line 194) | def to_bytes(
method from_bytes (line 198) | def from_bytes(
method to_bytes (line 206) | def to_bytes(
method from_bytes (line 210) | def from_bytes(
method is_integer (line 218) | def is_integer(self) -> Literal[True]: ...
method __add__ (line 220) | def __add__(self, value: int, /) -> int: ...
method __sub__ (line 221) | def __sub__(self, value: int, /) -> int: ...
method __mul__ (line 222) | def __mul__(self, value: int, /) -> int: ...
method __floordiv__ (line 223) | def __floordiv__(self, value: int, /) -> int: ...
method __truediv__ (line 224) | def __truediv__(self, value: int, /) -> float: ...
method __mod__ (line 225) | def __mod__(self, value: int, /) -> int: ...
method __divmod__ (line 226) | def __divmod__(self, value: int, /) -> tuple[int, int]: ...
method __radd__ (line 227) | def __radd__(self, value: int, /) -> int: ...
method __rsub__ (line 228) | def __rsub__(self, value: int, /) -> int: ...
method __rmul__ (line 229) | def __rmul__(self, value: int, /) -> int: ...
method __rfloordiv__ (line 230) | def __rfloordiv__(self, value: int, /) -> int: ...
method __rtruediv__ (line 231) | def __rtruediv__(self, value: int, /) -> float: ...
method __rmod__ (line 232) | def __rmod__(self, value: int, /) -> int: ...
method __rdivmod__ (line 233) | def __rdivmod__(self, value: int, /) -> tuple[int, int]: ...
method __pow__ (line 235) | def __pow__(self, x: Literal[0], /) -> Literal[1]: ...
method __pow__ (line 237) | def __pow__(self, value: Literal[0], mod: None, /) -> Literal[1]: ...
method __pow__ (line 239) | def __pow__(self, value: _PositiveInteger, mod: None = None, /) -> int...
method __pow__ (line 241) | def __pow__(self, value: _NegativeInteger, mod: None = None, /) -> flo...
method __pow__ (line 243) | def __pow__(self, value: int, mod: None = None, /) -> Any: ...
method __pow__ (line 245) | def __pow__(self, value: int, mod: int, /) -> int: ...
method __rpow__ (line 246) | def __rpow__(self, value: int, mod: int | None = None, /) -> Any: ...
method __and__ (line 247) | def __and__(self, value: int, /) -> int: ...
method __or__ (line 248) | def __or__(self, value: int, /) -> int: ...
method __xor__ (line 249) | def __xor__(self, value: int, /) -> int: ...
method __lshift__ (line 250) | def __lshift__(self, value: int, /) -> int: ...
method __rshift__ (line 251) | def __rshift__(self, value: int, /) -> int: ...
method __rand__ (line 252) | def __rand__(self, value: int, /) -> int: ...
method __ror__ (line 253) | def __ror__(self, value: int, /) -> int: ...
method __rxor__ (line 254) | def __rxor__(self, value: int, /) -> int: ...
method __rlshift__ (line 255) | def __rlshift__(self, value: int, /) -> int: ...
method __rrshift__ (line 256) | def __rrshift__(self, value: int, /) -> int: ...
method __neg__ (line 257) | def __neg__(self) -> int: ...
method __pos__ (line 258) | def __pos__(self) -> int: ...
method __invert__ (line 259) | def __invert__(self) -> int: ...
method __trunc__ (line 260) | def __trunc__(self) -> int: ...
method __ceil__ (line 261) | def __ceil__(self) -> int: ...
method __floor__ (line 262) | def __floor__(self) -> int: ...
method __round__ (line 264) | def __round__(self, ndigits: SupportsIndex | None = None, /) -> int: ...
method __round__ (line 266) | def __round__(self, ndigits: SupportsIndex = ..., /) -> int: ...
method __getnewargs__ (line 268) | def __getnewargs__(self) -> tuple[int]: ...
method __eq__ (line 269) | def __eq__(self, value: object, /) -> bool: ...
method __ne__ (line 270) | def __ne__(self, value: object, /) -> bool: ...
method __lt__ (line 271) | def __lt__(self, value: int, /) -> bool: ...
method __le__ (line 272) | def __le__(self, value: int, /) -> bool: ...
method __gt__ (line 273) | def __gt__(self, value: int, /) -> bool: ...
method __ge__ (line 274) | def __ge__(self, value: int, /) -> bool: ...
method __float__ (line 275) | def __float__(self) -> float: ...
method __int__ (line 276) | def __int__(self) -> int: ...
method __abs__ (line 277) | def __abs__(self) -> int: ...
method __hash__ (line 278) | def __hash__(self) -> int: ...
method __bool__ (line 279) | def __bool__(self) -> bool: ...
method __index__ (line 280) | def __index__(self) -> int: ...
method __format__ (line 281) | def __format__(self, format_spec: str, /) -> str: ...
class float (line 284) | class float:
method __new__ (line 285) | def __new__(cls, x: ConvertibleToFloat = 0, /) -> Self: ...
method as_integer_ratio (line 286) | def as_integer_ratio(self) -> tuple[int, int]: ...
method hex (line 287) | def hex(self) -> str: ...
method is_integer (line 288) | def is_integer(self) -> bool: ...
method fromhex (line 290) | def fromhex(cls, string: str, /) -> Self: ...
method real (line 292) | def real(self) -> float: ...
method imag (line 294) | def imag(self) -> float: ...
method conjugate (line 295) | def conjugate(self) -> float: ...
method __add__ (line 296) | def __add__(self, value: float, /) -> float: ...
method __sub__ (line 297) | def __sub__(self, value: float, /) -> float: ...
method __mul__ (line 298) | def __mul__(self, value: float, /) -> float: ...
method __floordiv__ (line 299) | def __floordiv__(self, value: float, /) -> float: ...
method __truediv__ (line 300) | def __truediv__(self, value: float, /) -> float: ...
method __mod__ (line 301) | def __mod__(self, value: float, /) -> float: ...
method __divmod__ (line 302) | def __divmod__(self, value: float, /) -> tuple[float, float]: ...
method __pow__ (line 304) | def __pow__(self, value: int, mod: None = None, /) -> float: ...
method __pow__ (line 306) | def __pow__(self, value: float, mod: None = None, /) -> Any: ...
method __radd__ (line 307) | def __radd__(self, value: float, /) -> float: ...
method __rsub__ (line 308) | def __rsub__(self, value: float, /) -> float: ...
method __rmul__ (line 309) | def __rmul__(self, value: float, /) -> float: ...
method __rfloordiv__ (line 310) | def __rfloordiv__(self, value: float, /) -> float: ...
method __rtruediv__ (line 311) | def __rtruediv__(self, value: float, /) -> float: ...
method __rmod__ (line 312) | def __rmod__(self, value: float, /) -> float: ...
method __rdivmod__ (line 313) | def __rdivmod__(self, value: float, /) -> tuple[float, float]: ...
method __rpow__ (line 315) | def __rpow__(self, value: _PositiveInteger, mod: None = None, /) -> fl...
method __rpow__ (line 317) | def __rpow__(self, value: _NegativeInteger, mod: None = None, /) -> co...
method __rpow__ (line 319) | def __rpow__(self, value: float, mod: None = None, /) -> Any: ...
method __getnewargs__ (line 320) | def __getnewargs__(self) -> tuple[float]: ...
method __trunc__ (line 321) | def __trunc__(self) -> int: ...
method __ceil__ (line 322) | def __ceil__(self) -> int: ...
method __floor__ (line 323) | def __floor__(self) -> int: ...
method __round__ (line 325) | def __round__(self, ndigits: None = None, /) -> int: ...
method __round__ (line 327) | def __round__(self, ndigits: SupportsIndex, /) -> float: ...
method __eq__ (line 328) | def __eq__(self, value: object, /) -> bool: ...
method __ne__ (line 329) | def __ne__(self, value: object, /) -> bool: ...
method __lt__ (line 330) | def __lt__(self, value: float, /) -> bool: ...
method __le__ (line 331) | def __le__(self, value: float, /) -> bool: ...
method __gt__ (line 332) | def __gt__(self, value: float, /) -> bool: ...
method __ge__ (line 333) | def __ge__(self, value: float, /) -> bool: ...
method __neg__ (line 334) | def __neg__(self) -> float: ...
method __pos__ (line 335) | def __pos__(self) -> float: ...
method __int__ (line 336) | def __int__(self) -> int: ...
method __float__ (line 337) | def __float__(self) -> float: ...
method __abs__ (line 338) | def __abs__(self) -> float: ...
method __hash__ (line 339) | def __hash__(self) -> int: ...
method __bool__ (line 340) | def __bool__(self) -> bool: ...
method __format__ (line 341) | def __format__(self, format_spec: str, /) -> str: ...
method from_number (line 344) | def from_number(cls, number: float | SupportsIndex | SupportsFloat, /)...
class _FormatMapMapping (line 347) | class _FormatMapMapping(Protocol):
method __getitem__ (line 348) | def __getitem__(self, key: str, /) -> Any: ...
class _TranslateTable (line 351) | class _TranslateTable(Protocol):
method __getitem__ (line 352) | def __getitem__(self, key: int, /) -> str | int | None: ...
class str (line 355) | class str(Sequence[str]):
method __new__ (line 357) | def __new__(cls, object: object = '') -> Self: ...
method __new__ (line 359) | def __new__(cls, object: ReadableBuffer, encoding: str = 'utf-8', erro...
method capitalize (line 361) | def capitalize(self: LiteralString) -> LiteralString: ...
method capitalize (line 363) | def capitalize(self) -> str: ...
method casefold (line 365) | def casefold(self: LiteralString) -> LiteralString: ...
method casefold (line 367) | def casefold(self) -> str: ...
method center (line 369) | def center(self: LiteralString, width: SupportsIndex, fillchar: Litera...
method center (line 371) | def center(self, width: SupportsIndex, fillchar: str = ' ', /) -> str:...
method count (line 372) | def count(self, sub: str, start: SupportsIndex | None = None, end: Sup...
method encode (line 373) | def encode(self, encoding: str = 'utf-8', errors: str = 'strict') -> b...
method endswith (line 374) | def endswith(
method expandtabs (line 378) | def expandtabs(self: LiteralString, tabsize: SupportsIndex = 8) -> Lit...
method expandtabs (line 380) | def expandtabs(self, tabsize: SupportsIndex = 8) -> str: ...
method find (line 381) | def find(self, sub: str, start: SupportsIndex | None = None, end: Supp...
method format (line 383) | def format(self: LiteralString, *args: LiteralString, **kwargs: Litera...
method format (line 385) | def format(self, *args: object, **kwargs: object) -> str: ...
method format_map (line 386) | def format_map(self, mapping: _FormatMapMapping, /) -> str: ...
method index (line 387) | def index(self, sub: str, start: SupportsIndex | None = None, end: Sup...
method isalnum (line 388) | def isalnum(self) -> bool: ...
method isalpha (line 389) | def isalpha(self) -> bool: ...
method isascii (line 390) | def isascii(self) -> bool: ...
method isdecimal (line 391) | def isdecimal(self) -> bool: ...
method isdigit (line 392) | def isdigit(self) -> bool: ...
method isidentifier (line 393) | def isidentifier(self) -> bool: ...
method islower (line 394) | def islower(self) -> bool: ...
method isnumeric (line 395) | def isnumeric(self) -> bool: ...
method isprintable (line 396) | def isprintable(self) -> bool: ...
method isspace (line 397) | def isspace(self) -> bool: ...
method istitle (line 398) | def istitle(self) -> bool: ...
method isupper (line 399) | def isupper(self) -> bool: ...
method join (line 401) | def join(self: LiteralString, iterable: Iterable[LiteralString], /) ->...
method join (line 403) | def join(self, iterable: Iterable[str], /) -> str: ...
method ljust (line 405) | def ljust(self: LiteralString, width: SupportsIndex, fillchar: Literal...
method ljust (line 407) | def ljust(self, width: SupportsIndex, fillchar: str = ' ', /) -> str: ...
method lower (line 409) | def lower(self: LiteralString) -> LiteralString: ...
method lower (line 411) | def lower(self) -> str: ...
method lstrip (line 413) | def lstrip(self: LiteralString, chars: LiteralString | None = None, /)...
method lstrip (line 415) | def lstrip(self, chars: str | None = None, /) -> str: ...
method partition (line 417) | def partition(self: LiteralString, sep: LiteralString, /) -> tuple[Lit...
method partition (line 419) | def partition(self, sep: str, /) -> tuple[str, str, str]: ...
method replace (line 422) | def replace(
method replace (line 426) | def replace(self, old: str, new: str, /, count: SupportsIndex = -1) ->...
method replace (line 429) | def replace(
method replace (line 433) | def replace(self, old: str, new: str, count: SupportsIndex = -1, /) ->...
method removeprefix (line 436) | def removeprefix(self: LiteralString, prefix: LiteralString, /) -> Lit...
method removeprefix (line 438) | def removeprefix(self, prefix: str, /) -> str: ...
method removesuffix (line 440) | def removesuffix(self: LiteralString, suffix: LiteralString, /) -> Lit...
method removesuffix (line 442) | def removesuffix(self, suffix: str, /) -> str: ...
method rfind (line 443) | def rfind(self, sub: str, start: SupportsIndex | None = None, end: Sup...
method rindex (line 444) | def rindex(self, sub: str, start: SupportsIndex | None = None, end: Su...
method rjust (line 446) | def rjust(self: LiteralString, width: SupportsIndex, fillchar: Literal...
method rjust (line 448) | def rjust(self, width: SupportsIndex, fillchar: str = ' ', /) -> str: ...
method rpartition (line 450) | def rpartition(
method rpartition (line 454) | def rpartition(self, sep: str, /) -> tuple[str, str, str]: ...
method rsplit (line 456) | def rsplit(
method rsplit (line 460) | def rsplit(self, sep: str | None = None, maxsplit: SupportsIndex = -1)...
method rstrip (line 462) | def rstrip(self: LiteralString, chars: LiteralString | None = None, /)...
method rstrip (line 464) | def rstrip(self, chars: str | None = None, /) -> str: ...
method split (line 466) | def split(
method split (line 470) | def split(self, sep: str | None = None, maxsplit: SupportsIndex = -1) ...
method splitlines (line 472) | def splitlines(self: LiteralString, keepends: bool = False) -> list[Li...
method splitlines (line 474) | def splitlines(self, keepends: bool = False) -> list[str]: ...
method startswith (line 475) | def startswith(
method strip (line 479) | def strip(self: LiteralString, chars: LiteralString | None = None, /) ...
method strip (line 481) | def strip(self, chars: str | None = None, /) -> str: ...
method swapcase (line 483) | def swapcase(self: LiteralString) -> LiteralString: ...
method swapcase (line 485) | def swapcase(self) -> str: ...
method title (line 487) | def title(self: LiteralString) -> LiteralString: ...
method title (line 489) | def title(self) -> str: ...
method translate (line 490) | def translate(self, table: _TranslateTable, /) -> str: ...
method upper (line 492) | def upper(self: LiteralString) -> LiteralString: ...
method upper (line 494) | def upper(self) -> str: ...
method zfill (line 496) | def zfill(self: LiteralString, width: SupportsIndex, /) -> LiteralStri...
method zfill (line 498) | def zfill(self, width: SupportsIndex, /) -> str: ...
method maketrans (line 501) | def maketrans(x: dict[int, _T] | dict[str, _T] | dict[str | int, _T], ...
method maketrans (line 504) | def maketrans(x: str, y: str, /) -> dict[int, int]: ...
method maketrans (line 507) | def maketrans(x: str, y: str, z: str, /) -> dict[int, int | None]: ...
method __add__ (line 509) | def __add__(self: LiteralString, value: LiteralString, /) -> LiteralSt...
method __add__ (line 511) | def __add__(self, value: str, /) -> str: ...
method __contains__ (line 512) | def __contains__(self, key: str, /) -> bool: ...
method __eq__ (line 513) | def __eq__(self, value: object, /) -> bool: ...
method __ge__ (line 514) | def __ge__(self, value: str, /) -> bool: ...
method __getitem__ (line 516) | def __getitem__(self: LiteralString, key: SupportsIndex | slice[Suppor...
method __getitem__ (line 518) | def __getitem__(self, key: SupportsIndex | slice[SupportsIndex | None]...
method __gt__ (line 519) | def __gt__(self, value: str, /) -> bool: ...
method __hash__ (line 520) | def __hash__(self) -> int: ...
method __iter__ (line 522) | def __iter__(self: LiteralString) -> Iterator[LiteralString]: ...
method __iter__ (line 524) | def __iter__(self) -> Iterator[str]: ...
method __le__ (line 525) | def __le__(self, value: str, /) -> bool: ...
method __len__ (line 526) | def __len__(self) -> int: ...
method __lt__ (line 527) | def __lt__(self, value: str, /) -> bool: ...
method __mod__ (line 529) | def __mod__(self: LiteralString, value: LiteralString | tuple[LiteralS...
method __mod__ (line 531) | def __mod__(self, value: Any, /) -> str: ...
method __mul__ (line 533) | def __mul__(self: LiteralString, value: SupportsIndex, /) -> LiteralSt...
method __mul__ (line 535) | def __mul__(self, value: SupportsIndex, /) -> str: ...
method __ne__ (line 536) | def __ne__(self, value: object, /) -> bool: ...
method __rmul__ (line 538) | def __rmul__(self: LiteralString, value: SupportsIndex, /) -> LiteralS...
method __rmul__ (line 540) | def __rmul__(self, value: SupportsIndex, /) -> str: ...
method __getnewargs__ (line 541) | def __getnewargs__(self) -> tuple[str]: ...
method __format__ (line 542) | def __format__(self, format_spec: str, /) -> str: ...
class bytes (line 545) | class bytes(Sequence[int]):
method __new__ (line 547) | def __new__(cls, o: Iterable[SupportsIndex] | SupportsIndex | Supports...
method __new__ (line 549) | def __new__(cls, string: str, /, encoding: str, errors: str = 'strict'...
method __new__ (line 551) | def __new__(cls) -> Self: ...
method capitalize (line 552) | def capitalize(self) -> bytes: ...
method center (line 553) | def center(self, width: SupportsIndex, fillchar: bytes = b' ', /) -> b...
method count (line 554) | def count(
method decode (line 561) | def decode(self, encoding: str = 'utf-8', errors: str = 'strict') -> s...
method endswith (line 562) | def endswith(
method expandtabs (line 569) | def expandtabs(self, tabsize: SupportsIndex = 8) -> bytes: ...
method find (line 570) | def find(
method hex (line 577) | def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = 1...
method index (line 578) | def index(
method isalnum (line 585) | def isalnum(self) -> bool: ...
method isalpha (line 586) | def isalpha(self) -> bool: ...
method isascii (line 587) | def isascii(self) -> bool: ...
method isdigit (line 588) | def isdigit(self) -> bool: ...
method islower (line 589) | def islower(self) -> bool: ...
method isspace (line 590) | def isspace(self) -> bool: ...
method istitle (line 591) | def istitle(self) -> bool: ...
method isupper (line 592) | def isupper(self) -> bool: ...
method join (line 593) | def join(self, iterable_of_bytes: Iterable[ReadableBuffer], /) -> byte...
method ljust (line 594) | def ljust(self, width: SupportsIndex, fillchar: bytes | bytearray = b'...
method lower (line 595) | def lower(self) -> bytes: ...
method lstrip (line 596) | def lstrip(self, bytes: ReadableBuffer | None = None, /) -> bytes: ...
method partition (line 597) | def partition(self, sep: ReadableBuffer, /) -> tuple[bytes, bytes, byt...
method replace (line 598) | def replace(self, old: ReadableBuffer, new: ReadableBuffer, count: Sup...
method removeprefix (line 599) | def removeprefix(self, prefix: ReadableBuffer, /) -> bytes: ...
method removesuffix (line 600) | def removesuffix(self, suffix: ReadableBuffer, /) -> bytes: ...
method rfind (line 601) | def rfind(
method rindex (line 608) | def rindex(
method rjust (line 615) | def rjust(self, width: SupportsIndex, fillchar: bytes | bytearray = b'...
method rpartition (line 616) | def rpartition(self, sep: ReadableBuffer, /) -> tuple[bytes, bytes, by...
method rsplit (line 617) | def rsplit(self, sep: ReadableBuffer | None = None, maxsplit: Supports...
method rstrip (line 618) | def rstrip(self, bytes: ReadableBuffer | None = None, /) -> bytes: ...
method split (line 619) | def split(self, sep: ReadableBuffer | None = None, maxsplit: SupportsI...
method splitlines (line 620) | def splitlines(self, keepends: bool = False) -> list[bytes]: ...
method startswith (line 621) | def startswith(
method strip (line 628) | def strip(self, bytes: ReadableBuffer | None = None, /) -> bytes: ...
method swapcase (line 629) | def swapcase(self) -> bytes: ...
method title (line 630) | def title(self) -> bytes: ...
method translate (line 631) | def translate(self, table: ReadableBuffer | None, /, delete: ReadableB...
method upper (line 632) | def upper(self) -> bytes: ...
method zfill (line 633) | def zfill(self, width: SupportsIndex, /) -> bytes: ...
method fromhex (line 636) | def fromhex(cls, string: str | ReadableBuffer, /) -> Self: ...
method fromhex (line 639) | def fromhex(cls, string: str, /) -> Self: ...
method maketrans (line 642) | def maketrans(frm: ReadableBuffer, to: ReadableBuffer, /) -> bytes: ...
method __len__ (line 643) | def __len__(self) -> int: ...
method __iter__ (line 644) | def __iter__(self) -> Iterator[int]: ...
method __hash__ (line 645) | def __hash__(self) -> int: ...
method __getitem__ (line 647) | def __getitem__(self, key: SupportsIndex, /) -> int: ...
method __getitem__ (line 649) | def __getitem__(self, key: slice[SupportsIndex | None], /) -> bytes: ...
method __add__ (line 650) | def __add__(self, value: ReadableBuffer, /) -> bytes: ...
method __mul__ (line 651) | def __mul__(self, value: SupportsIndex, /) -> bytes: ...
method __rmul__ (line 652) | def __rmul__(self, value: SupportsIndex, /) -> bytes: ...
method __mod__ (line 653) | def __mod__(self, value: Any, /) -> bytes: ...
method __contains__ (line 654) | def __contains__(self, key: SupportsIndex | ReadableBuffer, /) -> bool...
method __eq__ (line 655) | def __eq__(self, value: object, /) -> bool: ...
method __ne__ (line 656) | def __ne__(self, value: object, /) -> bool: ...
method __lt__ (line 657) | def __lt__(self, value: bytes, /) -> bool: ...
method __le__ (line 658) | def __le__(self, value: bytes, /) -> bool: ...
method __gt__ (line 659) | def __gt__(self, value: bytes, /) -> bool: ...
method __ge__ (line 660) | def __ge__(self, value: bytes, /) -> bool: ...
method __getnewargs__ (line 661) | def __getnewargs__(self) -> tuple[bytes]: ...
method __bytes__ (line 663) | def __bytes__(self) -> bytes: ...
method __buffer__ (line 665) | def __buffer__(self, flags: int, /) -> memoryview: ...
class bool (line 693) | class bool(int):
method __new__ (line 694) | def __new__(cls, o: object = False, /) -> Self: ...
method __and__ (line 696) | def __and__(self, value: bool, /) -> bool: ...
method __and__ (line 698) | def __and__(self, value: int, /) -> int: ...
method __or__ (line 700) | def __or__(self, value: bool, /) -> bool: ...
method __or__ (line 702) | def __or__(self, value: int, /) -> int: ...
method __xor__ (line 704) | def __xor__(self, value: bool, /) -> bool: ...
method __xor__ (line 706) | def __xor__(self, value: int, /) -> int: ...
method __rand__ (line 708) | def __rand__(self, value: bool, /) -> bool: ...
method __rand__ (line 710) | def __rand__(self, value: int, /) -> int: ...
method __ror__ (line 712) | def __ror__(self, value: bool, /) -> bool: ...
method __ror__ (line 714) | def __ror__(self, value: int, /) -> int: ...
method __rxor__ (line 716) | def __rxor__(self, value: bool, /) -> bool: ...
method __rxor__ (line 718) | def __rxor__(self, value: int, /) -> int: ...
method __getnewargs__ (line 719) | def __getnewargs__(self) -> tuple[int]: ...
method __invert__ (line 721) | def __invert__(self) -> int: ...
class slice (line 724) | class slice(Generic[_StartT_co, _StopT_co, _StepT_co]):
method start (line 726) | def start(self) -> _StartT_co: ...
method step (line 728) | def step(self) -> _StepT_co: ...
method stop (line 730) | def stop(self) -> _StopT_co: ...
method __new__ (line 732) | def __new__(cls, start: None, stop: None = None, step: None = None, /)...
method __new__ (line 734) | def __new__(cls, stop: _T2, /) -> slice[Any, _T2, Any]: ...
method __new__ (line 736) | def __new__(cls, start: _T1, stop: None, step: None = None, /) -> slic...
method __new__ (line 738) | def __new__(cls, start: None, stop: _T2, step: None = None, /) -> slic...
method __new__ (line 740) | def __new__(cls, start: _T1, stop: _T2, step: None = None, /) -> slice...
method __new__ (line 742) | def __new__(cls, start: None, stop: None, step: _T3, /) -> slice[Any, ...
method __new__ (line 744) | def __new__(cls, start: _T1, stop: None, step: _T3, /) -> slice[_T1, A...
method __new__ (line 746) | def __new__(cls, start: None, stop: _T2, step: _T3, /) -> slice[Any, _...
method __new__ (line 748) | def __new__(cls, start: _T1, stop: _T2, step: _T3, /) -> slice[_T1, _T...
method __eq__ (line 749) | def __eq__(self, value: object, /) -> bool: ...
method __hash__ (line 751) | def __hash__(self) -> int: ...
method indices (line 755) | def indices(self, len: SupportsIndex, /) -> tuple[int, int, int]: ...
class tuple (line 758) | class tuple(Sequence[_T_co]):
method __new__ (line 759) | def __new__(cls, iterable: Iterable[_T_co] = (), /) -> Self: ...
method __len__ (line 760) | def __len__(self) -> int: ...
method __contains__ (line 761) | def __contains__(self, key: object, /) -> bool: ...
method __getitem__ (line 763) | def __getitem__(self, key: SupportsIndex, /) -> _T_co: ...
method __getitem__ (line 765) | def __getitem__(self, key: slice[SupportsIndex | None], /) -> tuple[_T...
method __iter__ (line 766) | def __iter__(self) -> Iterator[_T_co]: ...
method __lt__ (line 767) | def __lt__(self, value: tuple[_T_co, ...], /) -> bool: ...
method __le__ (line 768) | def __le__(self, value: tuple[_T_co, ...], /) -> bool: ...
method __gt__ (line 769) | def __gt__(self, value: tuple[_T_co, ...], /) -> bool: ...
method __ge__ (line 770) | def __ge__(self, value: tuple[_T_co, ...], /) -> bool: ...
method __eq__ (line 771) | def __eq__(self, value: object, /) -> bool: ...
method __hash__ (line 772) | def __hash__(self) -> int: ...
method __add__ (line 774) | def __add__(self, value: tuple[_T_co, ...], /) -> tuple[_T_co, ...]: ...
method __add__ (line 776) | def __add__(self, value: tuple[_T, ...], /) -> tuple[_T_co | _T, ...]:...
method __mul__ (line 777) | def __mul__(self, value: SupportsIndex, /) -> tuple[_T_co, ...]: ...
method __rmul__ (line 778) | def __rmul__(self, value: SupportsIndex, /) -> tuple[_T_co, ...]: ...
method count (line 779) | def count(self, value: Any, /) -> int: ...
method index (line 780) | def index(self, value: Any, start: SupportsIndex = 0, stop: SupportsIn...
method __class_getitem__ (line 781) | def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
class list (line 784) | class list(MutableSequence[_T]):
method __init__ (line 786) | def __init__(self) -> None: ...
method __init__ (line 788) | def __init__(self, iterable: Iterable[_T], /) -> None: ...
method copy (line 789) | def copy(self) -> list[_T]: ...
method append (line 790) | def append(self, object: _T, /) -> None: ...
method extend (line 791) | def extend(self, iterable: Iterable[_T], /) -> None: ...
method pop (line 792) | def pop(self, index: SupportsIndex = -1, /) -> _T: ...
method index (line 793) | def index(self, value: _T, start: SupportsIndex = 0, stop: SupportsInd...
method count (line 794) | def count(self, value: _T, /) -> int: ...
method insert (line 795) | def insert(self, index: SupportsIndex, object: _T, /) -> None: ...
method remove (line 796) | def remove(self, value: _T, /) -> None: ...
method sort (line 798) | def sort(self: list[SupportsRichComparisonT], *, key: None = None, rev...
method sort (line 800) | def sort(self, *, key: Callable[[_T], SupportsRichComparison], reverse...
method __len__ (line 801) | def __len__(self) -> int: ...
method __iter__ (line 802) | def __iter__(self) -> Iterator[_T]: ...
method __getitem__ (line 806) | def __getitem__(self, i: SupportsIndex, /) -> _T: ...
method __getitem__ (line 808) | def __getitem__(self, s: slice[SupportsIndex | None], /) -> list[_T]: ...
method __setitem__ (line 810) | def __setitem__(self, key: SupportsIndex, value: _T, /) -> None: ...
method __setitem__ (line 812) | def __setitem__(self, key: slice[SupportsIndex | None], value: Iterabl...
method __delitem__ (line 813) | def __delitem__(self, key: SupportsIndex | slice[SupportsIndex | None]...
method __add__ (line 815) | def __add__(self, value: list[_T], /) -> list[_T]: ...
method __add__ (line 817) | def __add__(self, value: list[_S], /) -> list[_S | _T]: ...
method __iadd__ (line 818) | def __iadd__(self, value: Iterable[_T], /) -> Self: ...
method __mul__ (line 819) | def __mul__(self, value: SupportsIndex, /) -> list[_T]: ...
method __rmul__ (line 820) | def __rmul__(self, value: SupportsIndex, /) -> list[_T]: ...
method __imul__ (line 821) | def __imul__(self, value: SupportsIndex, /) -> Self: ...
method __contains__ (line 822) | def __contains__(self, key: object, /) -> bool: ...
method __reversed__ (line 823) | def __reversed__(self) -> Iterator[_T]: ...
method __gt__ (line 824) | def __gt__(self, value: list[_T], /) -> bool: ...
method __ge__ (line 825) | def __ge__(self, value: list[_T], /) -> bool: ...
method __lt__ (line 826) | def __lt__(self, value: list[_T], /) -> bool: ...
method __le__ (line 827) | def __le__(self, value: list[_T], /) -> bool: ...
method __eq__ (line 828) | def __eq__(self, value: object, /) -> bool: ...
method __class_getitem__ (line 829) | def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
class dict (line 832) | class dict(MutableMapping[_KT, _VT]):
method __init__ (line 834) | def __init__(self, /) -> None: ...
method __init__ (line 836) | def __init__(self: dict[str, _VT], /, **kwargs: _VT) -> None: ...
method __init__ (line 838) | def __init__(self, map: SupportsKeysAndGetItem[_KT, _VT], /) -> None: ...
method __init__ (line 840) | def __init__(self: dict[str, _VT], map: SupportsKeysAndGetItem[str, _V...
method __init__ (line 842) | def __init__(self, iterable: Iterable[tuple[_KT, _VT]], /) -> None: ...
method __init__ (line 844) | def __init__(self: dict[str, _VT], iterable: Iterable[tuple[str, _VT]]...
method __init__ (line 846) | def __init__(self: dict[str, str], iterable: Iterable[list[str]], /) -...
method __init__ (line 848) | def __init__(self: dict[bytes, bytes], iterable: Iterable[list[bytes]]...
method __new__ (line 849) | def __new__(cls, /, *args: Any, **kwargs: Any) -> Self: ...
method copy (line 850) | def copy(self) -> dict[_KT, _VT]: ...
method keys (line 851) | def keys(self) -> dict_keys[_KT, _VT]: ...
method values (line 852) | def values(self) -> dict_values[_KT, _VT]: ...
method items (line 853) | def items(self) -> dict_items[_KT, _VT]: ...
method fromkeys (line 856) | def fromkeys(cls, iterable: Iterable[_T], value: None = None, /) -> di...
method fromkeys (line 859) | def fromkeys(cls, iterable: Iterable[_T], value: _S, /) -> dict[_T, _S...
method get (line 861) | def get(self, key: _KT, default: None = None, /) -> _VT | None: ...
method get (line 863) | def get(self, key: _KT, default: _VT, /) -> _VT: ...
method get (line 865) | def get(self, key: _KT, default: _T, /) -> _VT | _T: ...
method pop (line 867) | def pop(self, key: _KT, /) -> _VT: ...
method pop (line 869) | def pop(self, key: _KT, default: _VT, /) -> _VT: ...
method pop (line 871) | def pop(self, key: _KT, default: _T, /) -> _VT | _T: ...
method __len__ (line 872) | def __len__(self) -> int: ...
method __getitem__ (line 873) | def __getitem__(self, key: _KT, /) -> _VT: ...
method __setitem__ (line 874) | def __setitem__(self, key: _KT, value: _VT, /) -> None: ...
method __delitem__ (line 875) | def __delitem__(self, key: _KT, /) -> None: ...
method __iter__ (line 876) | def __iter__(self) -> Iterator[_KT]: ...
method __eq__ (line 877) | def __eq__(self, value: object, /) -> bool: ...
method __reversed__ (line 878) | def __reversed__(self) -> Iterator[_KT]: ...
method __class_getitem__ (line 881) | def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
method __or__ (line 883) | def __or__(self, value: dict[_KT, _VT], /) -> dict[_KT, _VT]: ...
method __or__ (line 885) | def __or__(self, value: dict[_T1, _T2], /) -> dict[_KT | _T1, _VT | _T...
method __ror__ (line 887) | def __ror__(self, value: dict[_KT, _VT], /) -> dict[_KT, _VT]: ...
method __ror__ (line 889) | def __ror__(self, value: dict[_T1, _T2], /) -> dict[_KT | _T1, _VT | _...
method __ior__ (line 891) | def __ior__(self, value: SupportsKeysAndGetItem[_KT, _VT], /) -> Self:...
method __ior__ (line 893) | def __ior__(self, value: Iterable[tuple[_KT, _VT]], /) -> Self: ...
class set (line 896) | class set(MutableSet[_T]):
method __init__ (line 898) | def __init__(self) -> None: ...
method __init__ (line 900) | def __init__(self, iterable: Iterable[_T], /) -> None: ...
method add (line 901) | def add(self, element: _T, /) -> None: ...
method copy (line 902) | def copy(self) -> set[_T]: ...
method difference (line 903) | def difference(self, *s: Iterable[object]) -> set[_T]: ...
method difference_update (line 904) | def difference_update(self, *s: Iterable[object]) -> None: ...
method discard (line 905) | def discard(self, element: object, /) -> None: ...
method intersection (line 906) | def intersection(self, *s: Iterable[object]) -> set[_T]: ...
method intersection_update (line 907) | def intersection_update(self, *s: Iterable[object]) -> None: ...
method isdisjoint (line 908) | def isdisjoint(self, s: Iterable[object], /) -> bool: ...
method issubset (line 909) | def issubset(self, s: Iterable[object], /) -> bool: ...
method issuperset (line 910) | def issuperset(self, s: Iterable[object], /) -> bool: ...
method remove (line 911) | def remove(self, element: _T, /) -> None: ...
method symmetric_difference (line 912) | def symmetric_difference(self, s: Iterable[_S], /) -> set[_T | _S]: ...
method symmetric_difference_update (line 913) | def symmetric_difference_update(self, s: Iterable[_T], /) -> None: ...
method union (line 914) | def union(self, *s: Iterable[_S]) -> set[_T | _S]: ...
method update (line 915) | def update(self, *s: Iterable[_T]) -> None: ...
method __len__ (line 916) | def __len__(self) -> int: ...
method __contains__ (line 917) | def __contains__(self, o: object, /) -> bool: ...
method __iter__ (line 918) | def __iter__(self) -> Iterator[_T]: ...
method __and__ (line 919) | def __and__(self, value: AbstractSet[object], /) -> set[_T]: ...
method __iand__ (line 920) | def __iand__(self, value: AbstractSet[object], /) -> Self: ...
method __or__ (line 921) | def __or__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ...
method __ior__ (line 922) | def __ior__(self, value: AbstractSet[_T], /) -> Self: ...
method __sub__ (line 923) | def __sub__(self, value: AbstractSet[object], /) -> set[_T]: ...
method __isub__ (line 924) | def __isub__(self, value: AbstractSet[object], /) -> Self: ...
method __xor__ (line 925) | def __xor__(self, value: AbstractSet[_S], /) -> set[_T | _S]: ...
method __ixor__ (line 926) | def __ixor__(self, value: AbstractSet[_T], /) -> Self: ...
method __le__ (line 927) | def __le__(self, value: AbstractSet[object], /) -> bool: ...
method __lt__ (line 928) | def __lt__(self, value: AbstractSet[object], /) -> bool: ...
method __ge__ (line 929) | def __ge__(self, value: AbstractSet[object], /) -> bool: ...
method __gt__ (line 930) | def __gt__(self, value: AbstractSet[object], /) -> bool: ...
method __eq__ (line 931) | def __eq__(self, value: object, /) -> bool: ...
method __class_getitem__ (line 934) | def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
class frozenset (line 937) | class frozenset(AbstractSet[_T_co]):
method __new__ (line 939) | def __new__(cls) -> Self: ...
method __new__ (line 941) | def __new__(cls, iterable: Iterable[_T_co], /) -> Self: ...
method copy (line 942) | def copy(self) -> frozenset[_T_co]: ...
method difference (line 943) | def difference(self, *s: Iterable[object]) -> frozenset[_T_co]: ...
method intersection (line 944) | def intersection(self, *s: Iterable[object]) -> frozenset[_T_co]: ...
method isdisjoint (line 945) | def isdisjoint(self, s: Iterable[object], /) -> bool: ...
method issubset (line 946) | def issubset(self, s: Iterable[object], /) -> bool: ...
method issuperset (line 947) | def issuperset(self, s: Iterable[object], /) -> bool: ...
method symmetric_difference (line 948) | def symmetric_difference(self, s: Iterable[_S], /) -> frozenset[_T_co ...
method union (line 949) | def union(self, *s: Iterable[_S]) -> frozenset[_T_co | _S]: ...
method __len__ (line 950) | def __len__(self) -> int: ...
method __contains__ (line 951) | def __contains__(self, o: object, /) -> bool: ...
method __iter__ (line 952) | def __iter__(self) -> Iterator[_T_co]: ...
method __and__ (line 953) | def __and__(self, value: AbstractSet[object], /) -> frozenset[_T_co]: ...
method __or__ (line 954) | def __or__(self, value: AbstractSet[_S], /) -> frozenset[_T_co | _S]: ...
method __sub__ (line 955) | def __sub__(self, value: AbstractSet[object], /) -> frozenset[_T_co]: ...
method __xor__ (line 956) | def __xor__(self, value: AbstractSet[_S], /) -> frozenset[_T_co | _S]:...
method __le__ (line 957) | def __le__(self, value: AbstractSet[object], /) -> bool: ...
method __lt__ (line 958) | def __lt__(self, value: AbstractSet[object], /) -> bool: ...
method __ge__ (line 959) | def __ge__(self, value: AbstractSet[object], /) -> bool: ...
method __gt__ (line 960) | def __gt__(self, value: AbstractSet[object], /) -> bool: ...
method __eq__ (line 961) | def __eq__(self, value: object, /) -> bool: ...
method __hash__ (line 962) | def __hash__(self) -> int: ...
method __class_getitem__ (line 963) | def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
class enumerate (line 966) | class enumerate(Generic[_T]):
method __new__ (line 967) | def __new__(cls, iterable: Iterable[_T], start: int = 0) -> Self: ...
method __iter__ (line 968) | def __iter__(self) -> Self: ...
method __next__ (line 969) | def __next__(self) -> tuple[int, _T]: ...
method __class_getitem__ (line 970) | def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
class range (line 973) | class range(Sequence[int]):
method start (line 975) | def start(self) -> int: ...
method stop (line 977) | def stop(self) -> int: ...
method step (line 979) | def step(self) -> int: ...
method __new__ (line 981) | def __new__(cls, stop: SupportsIndex, /) -> Self: ...
method __new__ (line 983) | def __new__(cls, start: SupportsIndex, stop: SupportsIndex, step: Supp...
method count (line 984) | def count(self, value: int, /) -> int: ...
method index (line 985) | def index(self, value: int, /) -> int: ...
method __len__ (line 986) | def __len__(self) -> int: ...
method __eq__ (line 987) | def __eq__(self, value: object, /) -> bool: ...
method __hash__ (line 988) | def __hash__(self) -> int: ...
method __contains__ (line 989) | def __contains__(self, key: object, /) -> bool: ...
method __iter__ (line 990) | def __iter__(self) -> Iterator[int]: ...
method __getitem__ (line 992) | def __getitem__(self, key: SupportsIndex, /) -> int: ...
method __getitem__ (line 994) | def __getitem__(self, key: slice[SupportsIndex | None], /) -> range: ...
method __reversed__ (line 995) | def __reversed__(self) -> Iterator[int]: ...
class property (line 998) | class property:
method __init__ (line 1006) | def __init__(
method getter (line 1013) | def getter(self, fget: Callable[[Any], Any], /) -> property: ...
method setter (line 1014) | def setter(self, fset: Callable[[Any, Any], None], /) -> property: ...
method deleter (line 1015) | def deleter(self, fdel: Callable[[Any], None], /) -> property: ...
method __get__ (line 1017) | def __get__(self, instance: None, owner: type, /) -> Self: ...
method __get__ (line 1019) | def __get__(self, instance: Any, owner: type | None = None, /) -> Any:...
method __set__ (line 1020) | def __set__(self, instance: Any, value: Any, /) -> None: ...
method __delete__ (line 1021) | def __delete__(self, instance: Any, /) -> None: ...
function abs (line 1023) | def abs(x: SupportsAbs[_T], /) -> _T: ...
function all (line 1024) | def all(iterable: Iterable[object], /) -> bool: ...
function any (line 1025) | def any(iterable: Iterable[object], /) -> bool: ...
function bin (line 1026) | def bin(number: SupportsIndex, /) -> str: ...
function chr (line 1027) | def chr(i: SupportsIndex, /) -> str: ...
class _SupportsSynchronousAnext (line 1031) | class _SupportsSynchronousAnext(Protocol[_AwaitableT_co]):
method __anext__ (line 1032) | def __anext__(self) -> _AwaitableT_co: ...
function divmod (line 1038) | def divmod(x: SupportsDivMod[_T_contra, _T_co], y: _T_contra, /) -> _T_c...
function divmod (line 1040) | def divmod(x: _T_contra, y: SupportsRDivMod[_T_contra, _T_co], /) -> _T_...
function hash (line 1044) | def hash(obj: object, /) -> int: ...
function hex (line 1048) | def hex(number: SupportsIndex, /) -> str: ...
function id (line 1049) | def id(obj: object, /) -> int: ...
class _GetItemIterable (line 1051) | class _GetItemIterable(Protocol[_T_co]):
method __getitem__ (line 1052) | def __getitem__(self, i: int, /) -> _T_co: ...
function isinstance (line 1059) | def isinstance(obj: object, class_or_tuple: _ClassInfo, /) -> bool: ...
function len (line 1060) | def len(obj: Sized, /) -> int: ...
function max (line 1065) | def max(
function max (line 1069) | def max(arg1: _T, arg2: _T, /, *_args: _T, key: Callable[[_T], SupportsR...
function max (line 1071) | def max(iterable: Iterable[SupportsRichComparisonT], /, *, key: None = N...
function max (line 1073) | def max(iterable: Iterable[_T], /, *, key: Callable[[_T], SupportsRichCo...
function max (line 1075) | def max(
function max (line 1079) | def max(iterable: Iterable[_T1], /, *, key: Callable[[_T1], SupportsRich...
function min (line 1081) | def min(
function min (line 1085) | def min(arg1: _T, arg2: _T, /, *_args: _T, key: Callable[[_T], SupportsR...
function min (line 1087) | def min(iterable: Iterable[SupportsRichComparisonT], /, *, key: None = N...
function min (line 1089) | def min(iterable: Iterable[_T], /, *, key: Callable[[_T], SupportsRichCo...
function min (line 1091) | def min(
function min (line 1095) | def min(iterable: Iterable[_T1], /, *, key: Callable[[_T1], SupportsRich...
function oct (line 1096) | def oct(number: SupportsIndex, /) -> str: ...
function ord (line 1100) | def ord(c: str | bytes | bytearray, /) -> int: ...
class _SupportsWriteAndFlush (line 1102) | class _SupportsWriteAndFlush(SupportsWrite[_T_contra], SupportsFlush, Pr...
function print (line 1105) | def print(
function print (line 1113) | def print(
class _SupportsPow2 (line 1125) | class _SupportsPow2(Protocol[_E_contra, _T_co]):
method __pow__ (line 1126) | def __pow__(self, other: _E_contra, /) -> _T_co: ...
class _SupportsPow3NoneOnly (line 1129) | class _SupportsPow3NoneOnly(Protocol[_E_contra, _T_co]):
method __pow__ (line 1130) | def __pow__(self, other: _E_contra, modulo: None = None, /) -> _T_co: ...
class _SupportsPow3 (line 1133) | class _SupportsPow3(Protocol[_E_contra, _M_contra, _T_co]):
method __pow__ (line 1134) | def __pow__(self, other: _E_contra, modulo: _M_contra, /) -> _T_co: ...
function pow (line 1139) | def pow(base: int, exp: int, mod: int) -> int: ...
function pow (line 1141) | def pow(base: int, exp: Literal[0], mod: None = None) -> Literal[1]: ...
function pow (line 1143) | def pow(base: int, exp: _PositiveInteger, mod: None = None) -> int: ...
function pow (line 1145) | def pow(base: int, exp: _NegativeInteger, mod: None = None) -> float: ...
function pow (line 1147) | def pow(base: int, exp: int, mod: None = None) -> Any: ...
function pow (line 1149) | def pow(base: _PositiveInteger, exp: float, mod: None = None) -> float: ...
function pow (line 1151) | def pow(base: _NegativeInteger, exp: float, mod: None = None) -> complex...
function pow (line 1153) | def pow(base: float, exp: int, mod: None = None) -> float: ...
function pow (line 1155) | def pow(base: float, exp: complex | _SupportsSomeKindOfPow, mod: None = ...
function pow (line 1157) | def pow(base: complex, exp: complex | _SupportsSomeKindOfPow, mod: None ...
function pow (line 1159) | def pow(base: _SupportsPow2[_E_contra, _T_co], exp: _E_contra, mod: None...
function pow (line 1161) | def pow(base: _SupportsPow3NoneOnly[_E_contra, _T_co], exp: _E_contra, m...
function pow (line 1163) | def pow(base: _SupportsPow3[_E_contra, _M_contra, _T_co], exp: _E_contra...
function pow (line 1165) | def pow(base: _SupportsSomeKindOfPow, exp: float, mod: None = None) -> A...
function pow (line 1167) | def pow(base: _SupportsSomeKindOfPow, exp: complex, mod: None = None) ->...
class reversed (line 1172) | class reversed(Generic[_T]):
method __new__ (line 1174) | def __new__(cls, sequence: Reversible[_T], /) -> Iterator[_T]: ...
method __new__ (line 1176) | def __new__(cls, sequence: SupportsLenAndGetItem[_T], /) -> Iterator[_...
method __iter__ (line 1177) | def __iter__(self) -> Self: ...
method __next__ (line 1178) | def __next__(self) -> _T: ...
method __length_hint__ (line 1179) | def __length_hint__(self) -> int: ...
function repr (line 1181) | def repr(obj: object, /) -> str: ...
class _SupportsRound1 (line 1183) | class _SupportsRound1(Protocol[_T_co]):
method __round__ (line 1184) | def __round__(self) -> _T_co: ...
class _SupportsRound2 (line 1187) | class _SupportsRound2(Protocol[_T_co]):
method __round__ (line 1188) | def __round__(self, ndigits: int, /) -> _T_co: ...
function round (line 1191) | def round(number: _SupportsRound1[_T], ndigits: None = None) -> _T: ...
function round (line 1193) | def round(number: _SupportsRound2[_T], ndigits: SupportsIndex) -> _T: ...
function sorted (line 1195) | def sorted(
function sorted (line 1199) | def sorted(
class _SupportsSumWithNoDefaultGiven (line 1207) | class _SupportsSumWithNoDefaultGiven(SupportsAdd[Any, Any], SupportsRAdd...
function sum (line 1212) | def sum(iterable: Iterable[bool | _LiteralInteger], /, start: int = 0) -...
function sum (line 1214) | def sum(iterable: Iterable[_SupportsSumNoDefaultT], /) -> _SupportsSumNo...
function sum (line 1216) | def sum(iterable: Iterable[_AddableT1], /, start: _AddableT2) -> _Addabl...
class zip (line 1218) | class zip(Generic[_T_co]):
method __new__ (line 1221) | def __new__(cls, *, strict: bool = False) -> zip[Any]: ...
method __new__ (line 1223) | def __new__(cls, iter1: Iterable[_T1], /, *, strict: bool = False) -> ...
method __new__ (line 1225) | def __new__(
method __new__ (line 1229) | def __new__(
method __new__ (line 1233) | def __new__(
method __new__ (line 1244) | def __new__(
method __new__ (line 1256) | def __new__(
method __new__ (line 1270) | def __new__(cls) -> zip[Any]: ...
method __new__ (line 1272) | def __new__(cls, iter1: Iterable[_T1], /) -> zip[tuple[_T1]]: ...
method __new__ (line 1274) | def __new__(cls, iter1: Iterable[_T1], iter2: Iterable[_T2], /) -> zip...
method __new__ (line 1276) | def __new__(
method __new__ (line 1280) | def __new__(
method __new__ (line 1284) | def __new__(
method __new__ (line 1294) | def __new__(
method __iter__ (line 1306) | def __iter__(self) -> Self: ...
method __next__ (line 1307) | def __next__(self) -> _T_co: ...
class _NotImplementedType (line 1320) | class _NotImplementedType(Any): ...
class BaseException (line 1325) | class BaseException:
method __init__ (line 1332) | def __init__(self, *args: object) -> None: ...
method __new__ (line 1333) | def __new__(cls, *args: Any, **kwds: Any) -> Self: ...
method __setstate__ (line 1334) | def __setstate__(self, state: dict[str, Any] | None, /) -> None: ...
method with_traceback (line 1335) | def with_traceback(self, tb: TracebackType | None, /) -> Self: ...
method __str__ (line 1336) | def __str__(self) -> str: ...
method __repr__ (line 1337) | def __repr__(self) -> str: ...
method add_note (line 1341) | def add_note(self, note: str, /) -> None: ...
class KeyboardInterrupt (line 1343) | class KeyboardInterrupt(BaseException): ...
class SystemExit (line 1346) | class SystemExit(BaseException):
class Exception (line 1349) | class Exception(BaseException): ...
class StopIteration (line 1352) | class StopIteration(Exception):
class OSError (line 1356) | class OSError(Exception):
class ArithmeticError (line 1369) | class ArithmeticError(Exception): ...
class AssertionError (line 1370) | class AssertionError(Exception): ...
class AttributeError (line 1374) | class AttributeError(Exception):
method __init__ (line 1375) | def __init__(self, *args: object, name: str | None = None, obj: object...
class AttributeError (line 1380) | class AttributeError(Exception): ...
method __init__ (line 1375) | def __init__(self, *args: object, name: str | None = None, obj: object...
class LookupError (line 1382) | class LookupError(Exception): ...
class MemoryError (line 1383) | class MemoryError(Exception): ...
class NameError (line 1387) | class NameError(Exception):
method __init__ (line 1388) | def __init__(self, *args: object, name: str | None = None) -> None: ...
class NameError (line 1392) | class NameError(Exception): ...
method __init__ (line 1388) | def __init__(self, *args: object, name: str | None = None) -> None: ...
class RuntimeError (line 1394) | class RuntimeError(Exception): ...
class SyntaxError (line 1397) | class SyntaxError(Exception):
method __init__ (line 1409) | def __init__(self) -> None: ...
method __init__ (line 1411) | def __init__(self, msg: object, /) -> None: ...
method __init__ (line 1413) | def __init__(self, msg: str, info: tuple[str | None, int | None, int |...
method __init__ (line 1416) | def __init__(
class TypeError (line 1420) | class TypeError(Exception): ...
class ValueError (line 1421) | class ValueError(Exception): ...
class OverflowError (line 1422) | class OverflowError(ArithmeticError): ...
class ZeroDivisionError (line 1423) | class ZeroDivisionError(ArithmeticError): ...
class IndexError (line 1424) | class IndexError(LookupError): ...
class KeyError (line 1425) | class KeyError(LookupError): ...
class TimeoutError (line 1426) | class TimeoutError(OSError): ...
class NotImplementedError (line 1427) | class NotImplementedError(RuntimeError): ...
class RecursionError (line 1428) | class RecursionError(RuntimeError): ...
FILE: crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi
function namedtuple (line 47) | def namedtuple(
class UserDict (line 56) | class UserDict(MutableMapping[_KT, _VT]):
method __init__ (line 60) | def __init__(self, dict: None = None, /) -> None: ...
method __init__ (line 62) | def __init__(
method __init__ (line 69) | def __init__(self, dict: SupportsKeysAndGetItem[_KT, _VT], /) -> None:...
method __init__ (line 71) | def __init__(
method __init__ (line 78) | def __init__(self, iterable: Iterable[tuple[_KT, _VT]], /) -> None: ...
method __init__ (line 80) | def __init__(
method __init__ (line 87) | def __init__(self: UserDict[str, str], iterable: Iterable[list[str]], ...
method __init__ (line 89) | def __init__(self: UserDict[bytes, bytes], iterable: Iterable[list[byt...
method __len__ (line 90) | def __len__(self) -> int: ...
method __getitem__ (line 91) | def __getitem__(self, key: _KT) -> _VT: ...
method __setitem__ (line 92) | def __setitem__(self, key: _KT, item: _VT) -> None: ...
method __delitem__ (line 93) | def __delitem__(self, key: _KT) -> None: ...
method __iter__ (line 94) | def __iter__(self) -> Iterator[_KT]: ...
method __contains__ (line 95) | def __contains__(self, key: object) -> bool: ...
method copy (line 96) | def copy(self) -> Self: ...
method __copy__ (line 97) | def __copy__(self) -> Self: ...
method fromkeys (line 104) | def fromkeys(cls, iterable: Iterable[_T], value: None = None) -> UserD...
method fromkeys (line 107) | def fromkeys(cls, iterable: Iterable[_T], value: _S) -> UserDict[_T, _..
Condensed preview — 724 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,368K chars).
[
{
"path": ".cargo/config.toml",
"chars": 117,
"preview": "[env]\n# Use the project's venv Python for PyO3 builds\nPYO3_PYTHON = { value = \".venv/bin/python3\", relative = true }\n"
},
{
"path": ".claude/settings.json",
"chars": 1529,
"preview": "{\n \"permissions\": {\n \"allow\": [\n \"Bash(cargo:*)\",\n \"Bash(timeout 30s cargo:*)\",\n \"Bash(timeout 10s ca"
},
{
"path": ".claude/skills/coverage/SKILL.md",
"chars": 1119,
"preview": "---\nname: coverage\ndescription: Fetch coverage diff from Codecov for the current branch or a specific PR. Shows uncovere"
},
{
"path": ".claude/skills/fastmod/SKILL.md",
"chars": 700,
"preview": "---\nname: fastmod\ndescription: Use fastmod to make mass code updates to avoid many repetitive changes.\n---\n\n# fastmod\n\n#"
},
{
"path": ".claude/skills/python-playground/SKILL.md",
"chars": 1629,
"preview": "---\nname: python-playground\ndescription: Run and test Python code in a dedicated playground directory. Use when you need"
},
{
"path": ".codecov.yml",
"chars": 187,
"preview": "codecov:\n require_ci_to_pass: false\n\ncoverage:\n precision: 2\n # range: [90, 100]\n status:\n patch: false\n proje"
},
{
"path": ".github/actions/build-pgo-wheel/action.yml",
"chars": 2326,
"preview": "name: Build PGO wheel\ndescription: Builds a PGO-optimized wheel for pydantic-monty\n\ninputs:\n interpreter:\n descripti"
},
{
"path": ".github/workflows/ci.yml",
"chars": 24307,
"preview": "name: ci\n\non:\n push:\n branches:\n - main\n tags:\n - \"**\"\n pull_request: {}\n workflow_dispatch:\n inpu"
},
{
"path": ".github/workflows/codspeed.yml",
"chars": 898,
"preview": "name: CodSpeed\n\non:\n push:\n branches:\n - main\n pull_request:\n workflow_dispatch:\n\npermissions:\n contents: re"
},
{
"path": ".github/workflows/init-npm-packages.yml",
"chars": 2934,
"preview": "name: Initialize NPM Platform Packages\n\n# Creates placeholder packages on npm for any new napi platform targets.\n# npm r"
},
{
"path": ".gitignore",
"chars": 258,
"preview": "*.py[cod]\n*.so\n/.idea/\n/target/\n/env*/\n/*.py\n/TODO.md\n/monty\n/.claude/settings.local.json\n/scratch/\n/worktrees/\n/flame/\n"
},
{
"path": ".pre-commit-config.yaml",
"chars": 1230,
"preview": "fail_fast: true\n\nrepos:\n - repo: https://github.com/pre-commit/pre-commit-hooks\n rev: v4.0.1\n hooks:\n - id: "
},
{
"path": ".python-version",
"chars": 5,
"preview": "3.14\n"
},
{
"path": ".rustfmt.toml",
"chars": 104,
"preview": "max_width = 120\nimports_granularity = \"Crate\"\ngroup_imports = \"StdExternalCrate\"\nreorder_imports = true\n"
},
{
"path": "CLAUDE.md",
"chars": 22299,
"preview": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## "
},
{
"path": "Cargo.toml",
"chars": 3303,
"preview": "[workspace]\nresolver = \"2\"\nmembers = [\n \"crates/monty\",\n \"crates/monty-cli\",\n \"crates/monty-python\",\n \"crate"
},
{
"path": "LICENSE",
"chars": 1100,
"preview": "The MIT License (MIT)\n\nCopyright (c) Pydantic Services Inc. 2026 to present\n\nPermission is hereby granted, free of charg"
},
{
"path": "Makefile",
"chars": 8168,
"preview": ".DEFAULT_GOAL := main\n\n.PHONY: .cargo\n.cargo: ## Check that cargo is installed\n\t@cargo --version || echo 'Please install"
},
{
"path": "README.md",
"chars": 18501,
"preview": "<div align=\"center\">\n <h1>Monty</h1>\n</div>\n<div align=\"center\">\n <h3>A minimal, secure Python interpreter written in "
},
{
"path": "RELEASING.md",
"chars": 1140,
"preview": "# Release Process\n\n## 1. Bump Version\n\nUpdate version in both files:\n\n```bash\n# Edit Cargo.toml - update workspace.packa"
},
{
"path": "crates/fuzz/Cargo.toml",
"chars": 533,
"preview": "[package]\nname = \"monty-fuzz\"\npublish = false\nversion = { workspace = true }\nedition = { workspace = true }\n\n[package.me"
},
{
"path": "crates/fuzz/fuzz_targets/string_input_panic.rs",
"chars": 1329,
"preview": "//! Fuzz target for testing that arbitrary Python code doesn't cause panics or crashes.\n//!\n//! This target feeds arbitr"
},
{
"path": "crates/fuzz/fuzz_targets/tokens_input_panic.rs",
"chars": 14102,
"preview": "//! Fuzz target using structured token input instead of random strings.\n//!\n//! This generates more syntactically plausi"
},
{
"path": "crates/monty/Cargo.toml",
"chars": 1916,
"preview": "[package]\nname = \"monty\"\nreadme = \"../../README.md\"\nversion = { workspace = true }\nlicense = { workspace = true }\nrust-v"
},
{
"path": "crates/monty/benches/main.rs",
"chars": 8575,
"preview": "// Use codspeed-criterion-compat when running on CodSpeed (CI), real criterion otherwise (for flamegraphs)\n#[cfg(not(cod"
},
{
"path": "crates/monty/build.rs",
"chars": 550,
"preview": "fn main() {\n // This ensures that tests can find the libpython shared library at runtime, even if it's not on\n // "
},
{
"path": "crates/monty/src/args.rs",
"chars": 27272,
"preview": "use std::vec::IntoIter;\n\nuse crate::{\n MontyObject, ResourceTracker,\n bytecode::VM,\n defer_drop, defer_drop_mut"
},
{
"path": "crates/monty/src/asyncio.rs",
"chars": 6286,
"preview": "//! Async/await support types for Monty.\n//!\n//! This module contains all async-related types including coroutines, futu"
},
{
"path": "crates/monty/src/builtins/abs.rs",
"chars": 1861,
"preview": "//! Implementation of the abs() builtin function.\n\nuse num_bigint::BigInt;\nuse num_traits::Signed;\n\nuse crate::{\n arg"
},
{
"path": "crates/monty/src/builtins/all.rs",
"chars": 874,
"preview": "//! Implementation of the all() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop, d"
},
{
"path": "crates/monty/src/builtins/any.rs",
"chars": 879,
"preview": "//! Implementation of the any() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop, d"
},
{
"path": "crates/monty/src/builtins/bin.rs",
"chars": 2007,
"preview": "//! Implementation of the bin() builtin function.\n\nuse num_bigint::BigInt;\nuse num_traits::Signed;\n\nuse crate::{\n arg"
},
{
"path": "crates/monty/src/builtins/chr.rs",
"chars": 1709,
"preview": "//! Implementation of the chr() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop,\n "
},
{
"path": "crates/monty/src/builtins/divmod.rs",
"chars": 6568,
"preview": "//! Implementation of the divmod() builtin function.\n\nuse num_bigint::BigInt;\nuse num_integer::Integer;\nuse smallvec::sm"
},
{
"path": "crates/monty/src/builtins/enumerate.rs",
"chars": 1678,
"preview": "//! Implementation of the enumerate() builtin function.\n\nuse smallvec::smallvec;\n\nuse crate::{\n args::ArgValues,\n "
},
{
"path": "crates/monty/src/builtins/filter.rs",
"chars": 2411,
"preview": "//! Implementation of the filter() builtin function.\n//!\n//! This module provides the filter() builtin which filters ele"
},
{
"path": "crates/monty/src/builtins/getattr.rs",
"chars": 2491,
"preview": "//! Implementation of the getattr() builtin function.\n\nuse crate::{\n ExcType,\n args::ArgValues,\n bytecode::{Cal"
},
{
"path": "crates/monty/src/builtins/hash.rs",
"chars": 958,
"preview": "//! Implementation of the hash() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop,\n"
},
{
"path": "crates/monty/src/builtins/hex.rs",
"chars": 2005,
"preview": "//! Implementation of the hex() builtin function.\n\nuse num_bigint::BigInt;\nuse num_traits::Signed;\n\nuse crate::{\n arg"
},
{
"path": "crates/monty/src/builtins/id.rs",
"chars": 872,
"preview": "//! Implementation of the id() builtin function.\n\nuse crate::{\n args::ArgValues, bytecode::VM, defer_drop, exception_"
},
{
"path": "crates/monty/src/builtins/isinstance.rs",
"chars": 2489,
"preview": "//! Implementation of the isinstance() builtin function.\n\nuse super::Builtins;\nuse crate::{\n args::ArgValues,\n byt"
},
{
"path": "crates/monty/src/builtins/len.rs",
"chars": 862,
"preview": "//! Implementation of the len() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop,\n "
},
{
"path": "crates/monty/src/builtins/map.rs",
"chars": 3404,
"preview": "//! Implementation of the map() builtin function.\n\nuse crate::{\n args::{ArgValues, KwargsValues},\n bytecode::VM,\n "
},
{
"path": "crates/monty/src/builtins/min_max.rs",
"chars": 9165,
"preview": "//! Implementation of the min() and max() builtin functions.\n\nuse std::cmp::Ordering;\n\nuse crate::{\n args::{ArgValues"
},
{
"path": "crates/monty/src/builtins/mod.rs",
"chars": 7028,
"preview": "//! Python builtin functions, types, and exception constructors.\n//!\n//! This module provides the interpreter-native imp"
},
{
"path": "crates/monty/src/builtins/next.rs",
"chars": 868,
"preview": "//! Implementation of the next() builtin function.\n\nuse crate::{\n args::ArgValues, bytecode::VM, defer_drop, exceptio"
},
{
"path": "crates/monty/src/builtins/oct.rs",
"chars": 2007,
"preview": "//! Implementation of the oct() builtin function.\n\nuse num_bigint::BigInt;\nuse num_traits::Signed;\n\nuse crate::{\n arg"
},
{
"path": "crates/monty/src/builtins/ord.rs",
"chars": 2344,
"preview": "//! Implementation of the ord() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop,\n "
},
{
"path": "crates/monty/src/builtins/pow.rs",
"chars": 12883,
"preview": "//! Implementation of the pow() builtin function.\n\nuse num_bigint::BigInt;\nuse num_traits::{Signed, ToPrimitive, Zero};\n"
},
{
"path": "crates/monty/src/builtins/print.rs",
"chars": 4692,
"preview": "//! Implementation of the print() builtin function.\n\nuse crate::{\n args::{ArgValues, KwargsValues},\n bytecode::VM,"
},
{
"path": "crates/monty/src/builtins/repr.rs",
"chars": 654,
"preview": "//! Implementation of the repr() builtin function.\n\nuse crate::{\n args::ArgValues, bytecode::VM, defer_drop, exceptio"
},
{
"path": "crates/monty/src/builtins/reversed.rs",
"chars": 843,
"preview": "//! Implementation of the reversed() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n exceptio"
},
{
"path": "crates/monty/src/builtins/round.rs",
"chars": 6112,
"preview": "//! Implementation of the round() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop,"
},
{
"path": "crates/monty/src/builtins/sorted.rs",
"chars": 4830,
"preview": "//! Implementation of the sorted() builtin function.\n\nuse itertools::Itertools;\n\nuse crate::{\n args::ArgValues,\n b"
},
{
"path": "crates/monty/src/builtins/sum.rs",
"chars": 2365,
"preview": "//! Implementation of the sum() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop, d"
},
{
"path": "crates/monty/src/builtins/type_.rs",
"chars": 565,
"preview": "//! Implementation of the type() builtin function.\n\nuse super::Builtins;\nuse crate::{\n args::ArgValues, bytecode::VM,"
},
{
"path": "crates/monty/src/builtins/zip.rs",
"chars": 2490,
"preview": "//! Implementation of the zip() builtin function.\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop_mu"
},
{
"path": "crates/monty/src/bytecode/builder.rs",
"chars": 28051,
"preview": "//! Builder for emitting bytecode during compilation.\n//!\n//! `CodeBuilder` provides methods for emitting opcodes and op"
},
{
"path": "crates/monty/src/bytecode/code.rs",
"chars": 10402,
"preview": "//! Code object containing compiled bytecode and metadata.\n//!\n//! A `Code` object represents a compiled function or mod"
},
{
"path": "crates/monty/src/bytecode/compiler.rs",
"chars": 137798,
"preview": "//! Bytecode compiler for transforming AST to bytecode.\n//!\n//! The compiler traverses the prepared AST (`PreparedNode` "
},
{
"path": "crates/monty/src/bytecode/mod.rs",
"chars": 717,
"preview": "//! Bytecode VM module for Monty.\n//!\n//! This module contains the bytecode representation, compiler, and virtual machin"
},
{
"path": "crates/monty/src/bytecode/op.rs",
"chars": 24043,
"preview": "//! Opcode definitions for the bytecode VM.\n//!\n//! Bytecode is stored as raw `Vec<u8>` for cache efficiency. The `Opcod"
},
{
"path": "crates/monty/src/bytecode/vm/async_exec.rs",
"chars": 44249,
"preview": "//! Async execution support for the VM.\n//!\n//! This module contains all async-related methods for the VM including:\n//!"
},
{
"path": "crates/monty/src/bytecode/vm/attr.rs",
"chars": 2171,
"preview": "//! Attribute access helpers for the VM.\n\nuse super::VM;\nuse crate::{\n bytecode::vm::CallResult,\n defer_drop,\n "
},
{
"path": "crates/monty/src/bytecode/vm/binary.rs",
"chars": 16381,
"preview": "//! Binary and in-place operation helpers for the VM.\n\nuse super::VM;\nuse crate::{\n defer_drop,\n exception_private"
},
{
"path": "crates/monty/src/bytecode/vm/call.rs",
"chars": 31029,
"preview": "//! Function call helpers for the VM.\n//!\n//! This module contains the implementation of call-related opcodes and helper"
},
{
"path": "crates/monty/src/bytecode/vm/collections.rs",
"chars": 30800,
"preview": "//! Collection building and unpacking helpers for the VM.\n\nuse smallvec::SmallVec;\n\nuse super::VM;\nuse crate::{\n defe"
},
{
"path": "crates/monty/src/bytecode/vm/compare.rs",
"chars": 4834,
"preview": "//! Comparison operation helpers for the VM.\n\nuse super::VM;\nuse crate::{\n defer_drop,\n exception_private::{ExcTyp"
},
{
"path": "crates/monty/src/bytecode/vm/exceptions.rs",
"chars": 12778,
"preview": "//! Exception handling helpers for the VM.\n\nuse super::VM;\nuse crate::{\n builtins::Builtins,\n defer_drop,\n exce"
},
{
"path": "crates/monty/src/bytecode/vm/format.rs",
"chars": 5402,
"preview": "//! F-string and value formatting helpers for the VM.\n\nuse super::VM;\nuse crate::{\n defer_drop,\n exception_private"
},
{
"path": "crates/monty/src/bytecode/vm/mod.rs",
"chars": 87577,
"preview": "//! Bytecode virtual machine for executing compiled Python code.\n//!\n//! The VM uses a stack-based execution model with "
},
{
"path": "crates/monty/src/bytecode/vm/scheduler.rs",
"chars": 23707,
"preview": "//! Task scheduler for async execution and call ID allocation.\n//!\n//! # Task Model\n//!\n//! - Task 0 is the \"main task\" "
},
{
"path": "crates/monty/src/exception_private.rs",
"chars": 59277,
"preview": "use std::{\n borrow::Cow,\n fmt::{self, Display, Write},\n};\n\nuse serde::{Deserialize, Serialize};\nuse smallvec::smal"
},
{
"path": "crates/monty/src/exception_public.rs",
"chars": 12265,
"preview": "use std::fmt::{self, Write};\n\nuse crate::{\n exception_private::{ExcType, RawStackFrame},\n intern::Interns,\n par"
},
{
"path": "crates/monty/src/expressions.rs",
"chars": 27473,
"preview": "use crate::{\n args::ArgExprs,\n builtins::Builtins,\n fstring::FStringPart,\n intern::{BytesId, LongIntId, Stri"
},
{
"path": "crates/monty/src/fstring.rs",
"chars": 29885,
"preview": "//! F-string type definitions and formatting functions.\n//!\n//! This module contains the AST types for f-strings (format"
},
{
"path": "crates/monty/src/function.rs",
"chars": 5199,
"preview": "use std::fmt::Write;\n\nuse crate::{bytecode::Code, expressions::Identifier, intern::Interns, namespace::NamespaceId, sign"
},
{
"path": "crates/monty/src/heap.rs",
"chars": 42318,
"preview": "use std::{\n cell::Cell,\n collections::hash_map::DefaultHasher,\n hash::{Hash, Hasher},\n mem::size_of,\n vec"
},
{
"path": "crates/monty/src/heap_data.rs",
"chars": 50707,
"preview": "use std::{\n borrow::Cow,\n fmt::Write,\n hash::{DefaultHasher, Hash, Hasher},\n mem::discriminant,\n};\n\nuse ahas"
},
{
"path": "crates/monty/src/heap_traits.rs",
"chars": 14291,
"preview": "use std::{mem::ManuallyDrop, ptr::addr_of};\n\nuse crate::{\n ResourceTracker,\n heap::{Heap, HeapId, RecursionToken},"
},
{
"path": "crates/monty/src/intern.rs",
"chars": 22976,
"preview": "//! String, bytes, and long integer interning for efficient storage of literals and identifiers.\n//!\n//! This module pro"
},
{
"path": "crates/monty/src/io.rs",
"chars": 4157,
"preview": "use std::borrow::Cow;\n\nuse crate::exception_public::MontyException;\n\n/// Output handler for the `print()` builtin functi"
},
{
"path": "crates/monty/src/lib.rs",
"chars": 1305,
"preview": "#![doc = include_str!(\"../../../README.md\")]\n// first to include defer_drop macro\nmod heap_traits;\n\nmod args;\nmod asynci"
},
{
"path": "crates/monty/src/modules/asyncio.rs",
"chars": 5496,
"preview": "//! Implementation of the `asyncio` module.\n//!\n//! Provides a minimal implementation of Python's `asyncio` module with:"
},
{
"path": "crates/monty/src/modules/math.rs",
"chars": 52304,
"preview": "//! Implementation of Python's `math` module.\n//!\n//! Provides mathematical functions and constants matching CPython 3.1"
},
{
"path": "crates/monty/src/modules/mod.rs",
"chars": 4341,
"preview": "//! Built-in module implementations.\n//!\n//! This module provides implementations for Python built-in modules like `sys`"
},
{
"path": "crates/monty/src/modules/os.rs",
"chars": 4087,
"preview": "//! Implementation of the `os` module.\n//!\n//! Provides a minimal implementation of Python's `os` module with:\n//! - `ge"
},
{
"path": "crates/monty/src/modules/pathlib.rs",
"chars": 1165,
"preview": "//! Implementation of the `pathlib` module.\n//!\n//! Provides a minimal implementation of Python's `pathlib` module with:"
},
{
"path": "crates/monty/src/modules/re.rs",
"chars": 23620,
"preview": "//! Implementation of the `re` module.\n//!\n//! Provides regular expression matching operations.\n//! Uses the Rust `fancy"
},
{
"path": "crates/monty/src/modules/sys.rs",
"chars": 2298,
"preview": "//! Implementation of the `sys` module.\n//!\n//! Provides a minimal implementation of Python's `sys` module with:\n//! - `"
},
{
"path": "crates/monty/src/modules/typing.rs",
"chars": 2237,
"preview": "//! Implementation of the `typing` module.\n//!\n//! Provides a minimal implementation of Python's `typing` module with:\n/"
},
{
"path": "crates/monty/src/namespace.rs",
"chars": 754,
"preview": "/// Unique identifier for variable slots in namespaces (globals and function locals).\n///\n/// Used by the bytecode compi"
},
{
"path": "crates/monty/src/object.rs",
"chars": 42497,
"preview": "use std::{\n borrow::Cow,\n fmt::{self, Write},\n hash::{Hash, Hasher},\n};\n\nuse ahash::AHashSet;\nuse indexmap::Ind"
},
{
"path": "crates/monty/src/os.rs",
"chars": 8203,
"preview": "//! OS-level operations that require host system access.\n//!\n//! This module defines the `OsFunction` enum, which repres"
},
{
"path": "crates/monty/src/parse.rs",
"chars": 71631,
"preview": "use std::{borrow::Cow, fmt};\n\nuse num_bigint::BigInt;\nuse ruff_python_ast::{\n self as ast, BoolOp, CmpOp, ConversionF"
},
{
"path": "crates/monty/src/prepare.rs",
"chars": 137756,
"preview": "use std::collections::hash_map::Entry;\n\nuse ahash::{AHashMap, AHashSet};\n\nuse crate::{\n args::{ArgExprs, CallArg, Cal"
},
{
"path": "crates/monty/src/repl.rs",
"chars": 43235,
"preview": "//! Stateful REPL execution support for Monty.\n//!\n//! This module implements incremental snippet execution where each n"
},
{
"path": "crates/monty/src/resource.rs",
"chars": 21475,
"preview": "use std::{\n fmt,\n sync::atomic::{AtomicU16, Ordering},\n time::{Duration, Instant},\n};\n\nuse crate::{\n ExcType"
},
{
"path": "crates/monty/src/run.rs",
"chars": 19116,
"preview": "//! Public interface for running Monty code.\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse crate::{\n ExcType, "
},
{
"path": "crates/monty/src/run_progress.rs",
"chars": 29772,
"preview": "//! This module defines the public types returned by [`MontyRun::start()`](crate::MontyRun::start)\n//! and their resume "
},
{
"path": "crates/monty/src/signature.rs",
"chars": 27365,
"preview": "//! Function signature representation and argument binding.\n//!\n//! This module handles Python function signatures inclu"
},
{
"path": "crates/monty/src/sorting.rs",
"chars": 3277,
"preview": "//! Shared sorting utilities for `sorted()` and `list.sort()`.\n//!\n//! Both `sorted()` and `list.sort()` use index-based"
},
{
"path": "crates/monty/src/types/bytes.rs",
"chars": 79394,
"preview": "/// Python bytes type, wrapping a `Vec<u8>`.\n///\n/// This type provides Python bytes semantics with operations on ASCII "
},
{
"path": "crates/monty/src/types/dataclass.rs",
"chars": 12609,
"preview": "use std::fmt::Write;\n\nuse ahash::AHashSet;\n\nuse super::{Dict, PyTrait};\nuse crate::{\n args::ArgValues,\n bytecode::"
},
{
"path": "crates/monty/src/types/dict.rs",
"chars": 33200,
"preview": "use std::{\n collections::hash_map::DefaultHasher,\n fmt::Write,\n hash::{Hash, Hasher},\n};\n\nuse ahash::AHashSet;\n"
},
{
"path": "crates/monty/src/types/dict_view.rs",
"chars": 20143,
"preview": "use std::fmt::Write;\n\nuse ahash::AHashSet;\nuse smallvec::smallvec;\n\nuse crate::{\n args::ArgValues,\n bytecode::{Cal"
},
{
"path": "crates/monty/src/types/iter.rs",
"chars": 31412,
"preview": "//! Iterator support for Python for loops and the `iter()` type constructor.\n//!\n//! This module provides the `MontyIter"
},
{
"path": "crates/monty/src/types/list.rs",
"chars": 34747,
"preview": "use std::fmt::Write;\n\nuse ahash::AHashSet;\nuse itertools::Itertools;\nuse smallvec::SmallVec;\n\nuse super::{MontyIter, PyT"
},
{
"path": "crates/monty/src/types/long_int.rs",
"chars": 6655,
"preview": "//! LongInt wrapper for arbitrary precision integer support.\n//!\n//! This module provides the `LongInt` wrapper type aro"
},
{
"path": "crates/monty/src/types/mod.rs",
"chars": 1367,
"preview": "/// Type definitions for Python runtime values.\n///\n/// This module contains structured types that wrap heap-allocated d"
},
{
"path": "crates/monty/src/types/module.rs",
"chars": 5413,
"preview": "//! Python module type for representing imported modules.\n\nuse crate::{\n args::ArgValues,\n bytecode::{CallResult, "
},
{
"path": "crates/monty/src/types/namedtuple.rs",
"chars": 9094,
"preview": "/// Python named tuple type, combining tuple-like indexing with named attribute access.\n///\n/// Named tuples are like re"
},
{
"path": "crates/monty/src/types/path.rs",
"chars": 21998,
"preview": "//! Python `pathlib.Path` type implementation.\n//!\n//! Provides a path object with both pure methods (no I/O) and filesy"
},
{
"path": "crates/monty/src/types/property.rs",
"chars": 1299,
"preview": "//! Python property descriptor for computed attributes.\n//!\n//! Properties are descriptors whose value is computed when "
},
{
"path": "crates/monty/src/types/py_trait.rs",
"chars": 12746,
"preview": "/// Trait for heap-allocated Python values that need common operations.\n///\n/// This trait abstracts over container type"
},
{
"path": "crates/monty/src/types/range.rs",
"chars": 10059,
"preview": "//! Python range type implementation.\n//!\n//! Provides a range object that supports iteration over a sequence of integer"
},
{
"path": "crates/monty/src/types/re_match.rs",
"chars": 20219,
"preview": "//! Regex match result type for the `re` module.\n//!\n//! `ReMatch` represents the result of a successful regex match ope"
},
{
"path": "crates/monty/src/types/re_pattern.rs",
"chars": 29359,
"preview": "//! Compiled regex pattern type for the `re` module.\n//!\n//! `RePattern` wraps a compiled `fancy_regex::Regex` with the "
},
{
"path": "crates/monty/src/types/set.rs",
"chars": 51038,
"preview": "use std::fmt::Write;\n\nuse ahash::AHashSet;\nuse hashbrown::HashTable;\n\nuse super::{MontyIter, PyTrait};\nuse crate::{\n "
},
{
"path": "crates/monty/src/types/slice.rs",
"chars": 9914,
"preview": "//! Python slice type implementation.\n//!\n//! Provides a slice object representing start:stop:step indices for sequence "
},
{
"path": "crates/monty/src/types/str.rs",
"chars": 71516,
"preview": "/// Python string type, wrapping a Rust `String`.\n///\n/// This type provides Python string semantics. Currently supports"
},
{
"path": "crates/monty/src/types/tuple.rs",
"chars": 13830,
"preview": "/// Python tuple type using `SmallVec` for inline storage of small tuples.\n///\n/// This type provides Python tuple seman"
},
{
"path": "crates/monty/src/types/type.rs",
"chars": 16622,
"preview": "use std::fmt;\n\nuse num_bigint::BigInt;\n\nuse crate::{\n args::ArgValues,\n bytecode::VM,\n defer_drop,\n exceptio"
},
{
"path": "crates/monty/src/value.rs",
"chars": 110648,
"preview": "use std::{\n borrow::Cow,\n cmp::Ordering,\n collections::hash_map::DefaultHasher,\n fmt::{self, Write},\n has"
},
{
"path": "crates/monty/test_cases/args__dict_get_no_args.py",
"chars": 76,
"preview": "x = {}\nx.get()\n# Raise=TypeError('get expected at least 1 argument, got 0')\n"
},
{
"path": "crates/monty/test_cases/args__dict_get_too_many.py",
"chars": 83,
"preview": "x = {}\nx.get(1, 2, 3)\n# Raise=TypeError('get expected at most 2 arguments, got 3')\n"
},
{
"path": "crates/monty/test_cases/args__dict_items_with_args.py",
"chars": 81,
"preview": "x = {}\nx.items(1)\n# Raise=TypeError('dict.items() takes no arguments (1 given)')\n"
},
{
"path": "crates/monty/test_cases/args__dict_keys_with_args.py",
"chars": 79,
"preview": "x = {}\nx.keys(1)\n# Raise=TypeError('dict.keys() takes no arguments (1 given)')\n"
},
{
"path": "crates/monty/test_cases/args__dict_pop_no_args.py",
"chars": 76,
"preview": "x = {}\nx.pop()\n# Raise=TypeError('pop expected at least 1 argument, got 0')\n"
},
{
"path": "crates/monty/test_cases/args__dict_pop_too_many.py",
"chars": 83,
"preview": "x = {}\nx.pop(1, 2, 3)\n# Raise=TypeError('pop expected at most 2 arguments, got 3')\n"
},
{
"path": "crates/monty/test_cases/args__dict_values_with_args.py",
"chars": 83,
"preview": "x = {}\nx.values(1)\n# Raise=TypeError('dict.values() takes no arguments (1 given)')\n"
},
{
"path": "crates/monty/test_cases/args__id_too_many.py",
"chars": 72,
"preview": "id(1, 2)\n# Raise=TypeError('id() takes exactly one argument (2 given)')\n"
},
{
"path": "crates/monty/test_cases/args__len_no_args.py",
"chars": 70,
"preview": "len()\n# Raise=TypeError('len() takes exactly one argument (0 given)')\n"
},
{
"path": "crates/monty/test_cases/args__len_too_many.py",
"chars": 74,
"preview": "len(1, 2)\n# Raise=TypeError('len() takes exactly one argument (2 given)')\n"
},
{
"path": "crates/monty/test_cases/args__len_type_error_int.py",
"chars": 189,
"preview": "len(42)\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"args__len_type_error_int.py\", line 1, in <module>\n "
},
{
"path": "crates/monty/test_cases/args__len_type_error_none.py",
"chars": 201,
"preview": "len(None)\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"args__len_type_error_none.py\", line 1, in <module>\n "
},
{
"path": "crates/monty/test_cases/args__list_append_no_args.py",
"chars": 90,
"preview": "x = []\nx.append()\n# Raise=TypeError('list.append() takes exactly one argument (0 given)')\n"
},
{
"path": "crates/monty/test_cases/args__list_append_too_many.py",
"chars": 94,
"preview": "x = []\nx.append(1, 2)\n# Raise=TypeError('list.append() takes exactly one argument (2 given)')\n"
},
{
"path": "crates/monty/test_cases/args__list_insert_too_few.py",
"chars": 75,
"preview": "x = []\nx.insert(1)\n# Raise=TypeError('insert expected 2 arguments, got 1')\n"
},
{
"path": "crates/monty/test_cases/args__list_insert_too_many.py",
"chars": 81,
"preview": "x = []\nx.insert(1, 2, 3)\n# Raise=TypeError('insert expected 2 arguments, got 3')\n"
},
{
"path": "crates/monty/test_cases/args__repr_no_args.py",
"chars": 72,
"preview": "repr()\n# Raise=TypeError('repr() takes exactly one argument (0 given)')\n"
},
{
"path": "crates/monty/test_cases/arith__div_zero_float.py",
"chars": 56,
"preview": "1.0 / 0.0\n# Raise=ZeroDivisionError('division by zero')\n"
},
{
"path": "crates/monty/test_cases/arith__div_zero_int.py",
"chars": 52,
"preview": "1 / 0\n# Raise=ZeroDivisionError('division by zero')\n"
},
{
"path": "crates/monty/test_cases/arith__floordiv_zero_float.py",
"chars": 57,
"preview": "1.0 // 0.0\n# Raise=ZeroDivisionError('division by zero')\n"
},
{
"path": "crates/monty/test_cases/arith__floordiv_zero_int.py",
"chars": 53,
"preview": "1 // 0\n# Raise=ZeroDivisionError('division by zero')\n"
},
{
"path": "crates/monty/test_cases/arith__pow_zero_neg.py",
"chars": 60,
"preview": "0**-1\n# Raise=ZeroDivisionError('zero to a negative power')\n"
},
{
"path": "crates/monty/test_cases/arith__pow_zero_neg_builtin.py",
"chars": 200,
"preview": "pow(0, -1)\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"arith__pow_zero_neg_builtin.py\", line 1, in <module"
},
{
"path": "crates/monty/test_cases/assert__expr_fail.py",
"chars": 39,
"preview": "assert 1 == 2\n# Raise=AssertionError()\n"
},
{
"path": "crates/monty/test_cases/assert__fail.py",
"chars": 38,
"preview": "assert False\n# Raise=AssertionError()\n"
},
{
"path": "crates/monty/test_cases/assert__fail_msg.py",
"chars": 72,
"preview": "assert False, 'custom message'\n# Raise=AssertionError('custom message')\n"
},
{
"path": "crates/monty/test_cases/assert__fn_fail.py",
"chars": 46,
"preview": "# fmt: off\nassert(0)\n# Raise=AssertionError()\n"
},
{
"path": "crates/monty/test_cases/assert__ops.py",
"chars": 324,
"preview": "# Tests for assert statements that pass (failure cases are in separate files)\n# === Basic assert ===\nassert True, 'basic"
},
{
"path": "crates/monty/test_cases/async__asyncio_run.py",
"chars": 889,
"preview": "import asyncio\n\n\n# === Basic asyncio.run ===\nasync def simple():\n return 42\n\n\nresult = asyncio.run(simple())\nassert r"
},
{
"path": "crates/monty/test_cases/async__basic.py",
"chars": 199,
"preview": "# run-async\n# Basic async function that returns a value\n\n\nasync def foo():\n return 123\n\n\nresult = await foo() # pyri"
},
{
"path": "crates/monty/test_cases/async__closure.py",
"chars": 290,
"preview": "# run-async\n# Async function capturing variables from enclosing scope\n\n\ndef make_adder(n):\n async def adder(x):\n "
},
{
"path": "crates/monty/test_cases/async__double_await_coroutine.py",
"chars": 336,
"preview": "# run-async\nasync def foo():\n return 1\n\n\ncoro = foo()\nawait coro # pyright: ignore\nawait coro # pyright: ignore\n\"\"\""
},
{
"path": "crates/monty/test_cases/async__exception.py",
"chars": 214,
"preview": "# run-async\n# Test that exceptions in async functions propagate correctly\n\n\nasync def raises_error():\n raise ValueErr"
},
{
"path": "crates/monty/test_cases/async__ext_call.py",
"chars": 2594,
"preview": "# call-external\n# run-async\n# Test async external function calls (coroutines)\n\n# === Basic async external call ===\nresul"
},
{
"path": "crates/monty/test_cases/async__gather_all.py",
"chars": 2107,
"preview": "# run-async\nimport asyncio\n\n\n# === Basic gather ===\nasync def task1():\n return 1\n\n\nasync def task2():\n return 2\n\n\n"
},
{
"path": "crates/monty/test_cases/async__nested_await.py",
"chars": 243,
"preview": "# run-async\n# Nested async function calls\n\n\nasync def inner():\n return 42\n\n\nasync def outer():\n value = await inne"
},
{
"path": "crates/monty/test_cases/async__nested_gather_ext.py",
"chars": 1076,
"preview": "# call-external\n# run-async\n# Test nested asyncio.gather where outer gather spawns tasks that each\n# do a sequential ext"
},
{
"path": "crates/monty/test_cases/async__not_awaitable.py",
"chars": 237,
"preview": "# run-async\nawait 123 # pyright: ignore\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"async__not_awaitable."
},
{
"path": "crates/monty/test_cases/async__not_imported.py",
"chars": 359,
"preview": "# run-async\nasync def foo():\n return 1\n\n\nawait asyncio.gather(foo(), foo()) # pyright: ignore\n\"\"\"\nTRACEBACK:\nTraceba"
},
{
"path": "crates/monty/test_cases/async__recursion_depth_isolation.py",
"chars": 967,
"preview": "# call-external\n# run-async\n# Test that recursion depth is per-task, not global.\n#\n# With a recursion limit of 50, a gat"
},
{
"path": "crates/monty/test_cases/async__return_types.py",
"chars": 575,
"preview": "# run-async\n# Async functions returning different types\n\n\nasync def return_int():\n return 42\n\n\nasync def return_str()"
},
{
"path": "crates/monty/test_cases/async__sequential.py",
"chars": 352,
"preview": "# run-async\n# Multiple sequential awaits\n\n\nasync def get_value(x):\n return x * 2\n\n\na = await get_value(1) # pyright:"
},
{
"path": "crates/monty/test_cases/async__traceback.py",
"chars": 474,
"preview": "# run-async\n# Test that exceptions in async functions produce correct tracebacks\n\n\nasync def raises_error():\n raise V"
},
{
"path": "crates/monty/test_cases/async__with_args.py",
"chars": 341,
"preview": "# run-async\n# Async function with arguments\n\n\nasync def add(a, b):\n return a + b\n\n\nresult = await add(10, 20) # pyri"
},
{
"path": "crates/monty/test_cases/attr__get_int_error.py",
"chars": 181,
"preview": "x = 5\nx.foo\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"attr__get_int_error.py\", line 2, in <module>\n x"
},
{
"path": "crates/monty/test_cases/attr__get_list_error.py",
"chars": 191,
"preview": "x = [1, 2, 3]\nx.foo\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"attr__get_list_error.py\", line 2, in <modu"
},
{
"path": "crates/monty/test_cases/attr__set_frozen_nonfield.py",
"chars": 315,
"preview": "# call-external\n# Test that setting a non-field attribute on frozen dataclass raises error\npoint = make_point()\npoint.z "
},
{
"path": "crates/monty/test_cases/attr__set_int_error.py",
"chars": 242,
"preview": "x = 5\nx.foo = 1\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"attr__set_int_error.py\", line 2, in <module>\n "
},
{
"path": "crates/monty/test_cases/attr__set_list_error.py",
"chars": 252,
"preview": "x = [1, 2, 3]\nx.foo = 1\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"attr__set_list_error.py\", line 2, in <"
},
{
"path": "crates/monty/test_cases/bench__kitchen_sink.py",
"chars": 1363,
"preview": "# This test case is also used in the benchmark (benches/main.rs)\n# List operations\nmy_list = []\nmy_list.append(1)\nmy_lis"
},
{
"path": "crates/monty/test_cases/bool__ops.py",
"chars": 692,
"preview": "# === Boolean 'and' operator ===\n# returns first falsy value, or last value if all truthy\nassert (5 and 3) == 3, 'and tr"
},
{
"path": "crates/monty/test_cases/builtin__add_type_error.py",
"chars": 103,
"preview": "len + 1\n# Raise=TypeError(\"unsupported operand type(s) for +: 'builtin_function_or_method' and 'int'\")\n"
},
{
"path": "crates/monty/test_cases/builtin__filter.py",
"chars": 3127,
"preview": "assert list(filter(None, [0, 1, False, True, '', 'hello'])) == [1, True, 'hello'], 'filter None removes falsy values'\nas"
},
{
"path": "crates/monty/test_cases/builtin__filter_not_iterable.py",
"chars": 261,
"preview": "# filter() with non-iterable second argument\nfilter(None, 42)\n\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File "
},
{
"path": "crates/monty/test_cases/builtin__getattr.py",
"chars": 3079,
"preview": "# Test getattr() builtin function\n\ns = slice(1, 10, 2)\nassert getattr(s, 'start') == 1, 'getattr(slice, \"start\") should "
},
{
"path": "crates/monty/test_cases/builtin__iter_err_unpack_int.py",
"chars": 98,
"preview": "iterator = 0\n\niter(**42)\n# Raise=TypeError('iter() argument after ** must be a mapping, not int')\n"
},
{
"path": "crates/monty/test_cases/builtin__iter_funcs.py",
"chars": 1896,
"preview": "# === sum() ===\n# Basic sum operations\nassert sum([1, 2, 3]) == 6, 'sum of list'\nassert sum([1, 2, 3], 10) == 16, 'sum w"
},
{
"path": "crates/monty/test_cases/builtin__iter_next.py",
"chars": 2566,
"preview": "# === iter() on various iterables ===\n# iter() creates an iterator from an iterable\n\n# iter() on list\nit = iter([1, 2, 3"
},
{
"path": "crates/monty/test_cases/builtin__map.py",
"chars": 2972,
"preview": "assert list(map(abs, [-1, 0, 1, -2])) == [1, 0, 1, 2], 'map with abs'\nassert list(map(abs, [0, 0, 0])) == [0, 0, 0], 'ma"
},
{
"path": "crates/monty/test_cases/builtin__map_not_iterable.py",
"chars": 243,
"preview": "# map() with non-iterable second argument\nmap(abs, 42)\n\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"builti"
},
{
"path": "crates/monty/test_cases/builtin__math_funcs.py",
"chars": 5261,
"preview": "# === abs() ===\n# Basic abs operations\nassert abs(5) == 5, 'abs of positive int'\nassert abs(-5) == 5, 'abs of negative i"
},
{
"path": "crates/monty/test_cases/builtin__more_iter_funcs.py",
"chars": 14327,
"preview": "# === min() ===\n# Basic min operations\nassert min([1, 2, 3]) == 1, 'min of list'\nassert min([3, 1, 2]) == 1, 'min of uns"
},
{
"path": "crates/monty/test_cases/builtin__next_stop_iteration.py",
"chars": 179,
"preview": "it = iter([])\nnext(it)\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"builtin__next_stop_iteration.py\", line "
},
{
"path": "crates/monty/test_cases/builtin__print_invalid_kwarg.py",
"chars": 275,
"preview": "print('xxx', **{\"foo'\": 123})\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"builtin__print_invalid_kwarg.py\""
},
{
"path": "crates/monty/test_cases/builtin__print_kwargs.py",
"chars": 401,
"preview": "# Tests dynamic keyword arguments for print()\n\n# === Dynamic sep via **kwargs ===\ndynamic_sep = 's' + 'e' + 'p'\nresult ="
},
{
"path": "crates/monty/test_cases/builtin__repr.py",
"chars": 161,
"preview": "# === repr of built-in functions ===\nassert repr(len) == '<built-in function len>', 'repr(len)'\nassert repr(print) == '<"
},
{
"path": "crates/monty/test_cases/builtin__string_funcs.py",
"chars": 2429,
"preview": "# === ord() ===\n# Basic ord operations\nassert ord('a') == 97, 'ord lowercase a'\nassert ord('A') == 65, 'ord uppercase A'"
},
{
"path": "crates/monty/test_cases/bytes__decode_invalid_utf8.py",
"chars": 660,
"preview": "# Test that bytes.decode raises UnicodeDecodeError for invalid UTF-8\n# UnicodeDecodeError is a subclass of ValueError, s"
},
{
"path": "crates/monty/test_cases/bytes__endswith_str_error.py",
"chars": 316,
"preview": "# Test that bytes.endswith with str raises TypeError\nb'hello'.endswith('o')\n\"\"\"\nTRACEBACK:\nTraceback (most recent call l"
},
{
"path": "crates/monty/test_cases/bytes__getitem_index_error.py",
"chars": 184,
"preview": "b = b'hello'\nb[10]\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"bytes__getitem_index_error.py\", line 2, in "
},
{
"path": "crates/monty/test_cases/bytes__index_start_gt_end.py",
"chars": 312,
"preview": "# Test that bytes.index with start > end doesn't panic but raises ValueError\nb'hello'.index(b'e', 5, 2)\n\"\"\"\nTRACEBACK:\nT"
},
{
"path": "crates/monty/test_cases/bytes__methods.py",
"chars": 18138,
"preview": "# === bytes.decode() ===\nassert b'hello'.decode() == 'hello', 'decode default utf-8'\nassert b'hello'.decode('utf-8') == "
},
{
"path": "crates/monty/test_cases/bytes__negative_count.py",
"chars": 174,
"preview": "bytes(-1)\n\"\"\"\nTRACEBACK:\nTraceback (most recent call last):\n File \"bytes__negative_count.py\", line 1, in <module>\n b"
},
{
"path": "crates/monty/test_cases/bytes__ops.py",
"chars": 3177,
"preview": "# === Bytes length ===\nassert len(b'') == 0, 'len empty'\nassert len(b'hello') == 5, 'len basic'\n\n# === Bytes repr/str =="
},
{
"path": "crates/monty/test_cases/bytes__startswith_str_error.py",
"chars": 328,
"preview": "# Test that bytes.startswith with str raises TypeError\nb'hello'.startswith('h')\n\"\"\"\nTRACEBACK:\nTraceback (most recent ca"
},
{
"path": "crates/monty/test_cases/call_object.py",
"chars": 28,
"preview": "x = len\nx('abc')\n# Return=3\n"
}
]
// ... and 524 more files (download for full content)
About this extraction
This page contains the full source code of the pydantic/monty GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 724 files (4.0 MB), approximately 1.1M tokens, and a symbol index with 6669 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.