Conversation
Bumps [https://github.com/astral-sh/ruff-pre-commit](https://github.com/astral-sh/ruff-pre-commit) from v0.15.16 to 0.15.17. - [Release notes](https://github.com/astral-sh/ruff-pre-commit/releases) - [Commits](astral-sh/ruff-pre-commit@v0.15.16...v0.15.17) --- updated-dependencies: - dependency-name: https://github.com/astral-sh/ruff-pre-commit dependency-version: 0.15.17 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [github/gh-aw](https://github.com/github/gh-aw) from 0.77.5 to 0.79.9. - [Release notes](https://github.com/github/gh-aw/releases) - [Changelog](https://github.com/github/gh-aw/blob/main/CHANGELOG.md) - [Commits](github/gh-aw@f990bbb...54ad1f8) --- updated-dependencies: - dependency-name: github/gh-aw dependency-version: 0.79.9 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…RustPython#8145) Bumps [https://github.com/rbubley/mirrors-prettier](https://github.com/rbubley/mirrors-prettier) from v3.8.3 to 3.8.4. - [Commits](rbubley/mirrors-prettier@v3.8.3...v3.8.4) --- updated-dependencies: - dependency-name: https://github.com/rbubley/mirrors-prettier dependency-version: 3.8.4 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…n#8146) Bumps the malachite group with 2 updates in the / directory: [malachite-bigint](https://github.com/mhogrefe/malachite) and [malachite-q](https://github.com/mhogrefe/malachite). Updates `malachite-bigint` from 0.9.1 to 0.9.2 - [Release notes](https://github.com/mhogrefe/malachite/releases) - [Commits](mhogrefe/malachite@v0.9.1...v0.9.2) Updates `malachite-q` from 0.9.1 to 0.9.2 - [Release notes](https://github.com/mhogrefe/malachite/releases) - [Commits](mhogrefe/malachite@v0.9.1...v0.9.2) Updates `malachite-base` from 0.9.1 to 0.9.2 - [Release notes](https://github.com/mhogrefe/malachite/releases) - [Commits](mhogrefe/malachite@v0.9.1...v0.9.2) --- updated-dependencies: - dependency-name: malachite-bigint dependency-version: 0.9.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: malachite - dependency-name: malachite-q dependency-version: 0.9.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: malachite - dependency-name: malachite-base dependency-version: 0.9.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: malachite ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the random group with 1 update in the / directory: [getrandom](https://github.com/rust-random/getrandom). Updates `getrandom` from 0.4.2 to 0.4.3 - [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md) - [Commits](rust-random/getrandom@v0.4.2...v0.4.3) --- updated-dependencies: - dependency-name: getrandom dependency-version: 0.4.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: random ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…thon#8150) Bumps the webpki-root group with 1 update in the / directory: [webpki-roots](https://github.com/rustls/webpki-roots). Updates `webpki-roots` from 1.0.7 to 1.0.8 - [Release notes](https://github.com/rustls/webpki-roots/releases) - [Commits](rustls/webpki-roots@v/1.0.7...v/1.0.8) --- updated-dependencies: - dependency-name: webpki-roots dependency-version: 1.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: webpki-root ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [which](https://github.com/harryfei/which-rs) from 8.0.3 to 8.0.4. - [Release notes](https://github.com/harryfei/which-rs/releases) - [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md) - [Commits](harryfei/which-rs@8.0.3...8.0.4) --- updated-dependencies: - dependency-name: which dependency-version: 8.0.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.81.8 to 2.81.11. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](taiki-e/install-action@0631aa6...15449e3) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.81.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
RustPython#8155) * mark_except_handlers * mark_warm * mark_cold * push_cold_blocks_to_end * check_cfg * jump thread * basicblock_add_jump * convert_pseudo_conditional_jumps * normalize_jumps_in_block * basicblock_inline_small_or_no_lineno_blocks * inline_small_or_no_lineno_blocks * basicblock_remove_redundant_nops * remove_redundant_nops * no_redundant_nops * remove_redundant_jumps * no_redundant_jumps * remove_redundant_nops_and_jumps * blocks_new_block * clippy
* Update `test_repl.py` to 3.14.6 * mark failing tests * Mark failing test correctly
* Update `test_ssl.py` to 3.14.6 * Add `Lib/test/ssltests.py` * Mark failing test correctly
* Add `test_fileutils.py` from 3.14.6 * Align patch for `test_zipimport_support.py` * Update `test_bigmem.py` to 3.14.6 * Update `test_exception_group.py` * Align patches for `test_baseexception.py` * Update `test_exceptions.py` * Update `test_dtrace.py` * Remove patch from `string_tests.py`
* Align compiler and AST behavior with CPython
Update the compiler pipeline, AST module support, and related VM compile/eval paths toward CPython 3.14 behavior.
Use upstream Ruff parser crates directly and keep RustPython-specific syntax preflight handling in the compile path.
Refresh opcode metadata, snapshots, and targeted tests for the aligned bytecode and AST behavior.
* fix
* Fix PR 8138 CI failures
* Fix match mapping wildcard scan complexity
* fixes
* Use Ruff runtime AST fields
* Minimize residual patch diff
* refactor error handling
* Remove _ast conversion context wrappers
* Clean up _ast conversion glue and compiler warning escalation
Rename the Node conversion parameter `ctx` to `vm` throughout the _ast
module.
Remove the unused compile_program, compile_program_single,
compile_block_expression, and compile_expression forwarders; compile_top
stays as the entry point.
Stash an escalated compiler SyntaxWarning so a non-SyntaxWarning category
propagates unchanged instead of being rewritten to SyntaxError, matching
PyErr_ExceptionMatches(SyntaxWarning) in compiler_warn. Drop the now-unused
CompileWarningError::into_codegen_error.
Replace the PositionalArguments two-variant enum with a struct holding a
shared range and a PositionalArgumentsKind enum.
Assisted-by: Claude
* Represent compiler flags as a CompilerFlags bitflags
Replace the loose PY_CF_*/CO_* i32 constants in compile_mode with a
CompilerFlags bitflags covering the PyCF_* flags and __future__
CO_FUTURE_* bits. The Python-visible ast.PyCF_* attribute values are
derived from it via bits(); parser input modes stay plain consts.
builtins::compile and the compile_string flag handling test flags
through CompilerFlags::contains instead of raw bit math.
Assisted-by: Claude
* Fix PR 8138 test regressions
* Fix PR 8138 CI failures
* Avoid shell interpolation in Linux deps action
* Fix review findings in compiler/AST changes
- frame.rs: compute the MATCH_CLASS class name lazily so a successful
match no longer takes the type name lock or allocates; the
__match_args__-not-a-tuple branch reuses it instead of recomputing.
- _ast/constant.rs: add the missing leading space to the with_recursion
label ("maximum recursion depth exceeded during compilation").
- sys.set_int_max_str_digits: restore the "maxdigits must be 0 or larger
than {n}" error text.
- codegen: set CO_MAXBLOCKS to 20 in both ir.rs and compile.rs.
- _ast/exception.rs: extract the duplicated excepthandler node guard
into ensure_excepthandler_node.
- codegen: correct the validate_keywords doc comment.
- Drop redundant "CPython" qualifiers from comments added in this branch.
Assisted-by: Claude
* Update `test/signalinterproctester.py` to 3.14.6 * Add `signalinterproctester.py` as a test dependency of `test_signal.py`
* Fix all clippy suggestions in `ir.rs` * remove some `idx()` calls
* Add more int functions to the c-api * Simplify as_mask logic * Add `PyLong_FromNativeBytes` & `PyLong_FromUnsignedNativeBytes`
Assisted-by: WarpForgeAgent:DeepSeek-v4-flash
…tPython#8452) Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/fastify/fast-uri/releases) - [Commits](fastify/fast-uri@v3.1.4...v3.1.5) --- updated-dependencies: - dependency-name: fast-uri dependency-version: 3.1.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Assisted-by: Codex:gpt-5
Validate decimal integer literals from the parser token stream before lowering the parsed AST. Reuse the validator for normal compilation and the `_ast` parsing path so `PyCF_ONLY_AST`, `ast.parse()`, and `ast.literal_eval()` honor `int_max_str_digits` consistently. Remove the now-passing `test_literal_eval_str_int_limit` expected-failure marker. The token-based validator excludes non-decimal integers, floats, complex literals, strings, and comments without duplicating lexer logic. Assisted-by: Codex:gpt-5.6-sol
…ustPython#8431) * Factor with_iframe into enter_iframe/exit_iframe helpers Extract the frame entry (recursion check, TLS link, exception save) and exit (materialization sync, TLS restore, GC tracking) logic from with_iframe into standalone enter_iframe/exit_iframe methods. with_iframe now calls them, with no behavioral change. This prepares for the trampoline loop where enter/exit are called individually rather than wrapped around a closure. Assisted-by: Claude * Allocate InterpreterFrame and LocalsPlus together on the datastack Add InterpreterFrame::new_on_datastack() that bump-allocates both the InterpreterFrame struct and its LocalsPlus data array in a single datastack push, eliminating one allocation per function call. Update datastack_frame_size_bytes_for_code() to include InterpreterFrame size. Convert invoke_prepared_exact_args() and the invoke() fast path to use the combined allocation. Add release_datastack_frame() method on InterpreterFrame that drops all localsplus values, runs field destructors (trace, temporary_refs, retained_back, etc.), and returns the datastack base pointer for pop. Assisted-by: Claude * Implement trampoline loop for Python-to-Python calls Add ExecutionResult::TailCall variant and a trampoline in run_frame_fast that flattens Python-to-Python calls into a single Rust stack frame instead of recursing through the eval loop. CallPyExactArgs now prepares the callee frame on the datastack and returns TailCall when tailcall_enabled is set (run_iframe path only). The trampoline dispatches via a state machine (EnterCallee / ReturnValue / Unwind) in a single loop, avoiding mutual recursion between helper functions that would exhaust the C stack. Exception propagation through suspended frames uses trampoline_handle_exception which adds traceback entries and calls unwind_blocks on each caller. Assisted-by: Claude * Optimize trampoline: skip recursion check, avoid temporary_refs mutex, add bound method TailCall - Add enter_iframe_unchecked for trampoline callee entry (recursion already checked by specialization_call_recursion_guard) - Move callable ownership from per-frame temporary_refs mutex to trampoline-local SuspendedFrame.owned_refs via VM side channel - Add TailCall support for CallBoundMethodExactArgs - Move args directly from caller stack to callee fastlocals - Read materialized pointer once in exit_iframe Incremental call overhead: ~55 ns -> ~35 ns Assisted-by: Claude * Use UnsafeCell for pending_tailcall_refs The VM is per-thread so RefCell's runtime borrow checking is unnecessary overhead. Replace with UnsafeCell for direct access. Assisted-by: Claude * Remove .claude/settings.json from tracking Assisted-by: Claude * Replace SendPtr with Option<SendNonNull> for type-safe pending tailcall Use NonNull + Option instead of raw *mut T with manual null checks. The compiler enforces non-null via the type system, and Option<NonNull> has the same size as a raw pointer thanks to niche optimization. Also extract take_pending_tailcall helper to deduplicate the pattern. Assisted-by: Claude * Restrict PendingFrame to private, expose only set/take methods Rename SendNonNull to PendingFrame and make it fully private: the struct, its field, and the pending_tailcall_frame Cell are all non-pub. External code accesses the side channel only through set_pending_tailcall (pub(crate)) and take_pending_tailcall (private). This ensures the unsafe Send+Sync impl cannot be reused elsewhere without justifying a new safety argument. Assisted-by: Claude * Restore C-stack overflow check in trampoline enter_iframe_unchecked enter_iframe_unchecked was skipping C-stack checks under the assumption that the trampoline stays in one Rust stack frame. But each run_iframe call still consumes Rust stack, so deep Python recursion through the trampoline can exhaust the C stack (observed as STATUS_STACK_OVERFLOW on Windows CI). Keep the C-stack check (every 8th call) while still skipping the Python recursion depth check (already done by specialization_call_recursion_guard). Assisted-by: Claude * Address code review: entry frame double-free, panic safety, cleanup - Fix double-free: mark entry frame with is_entry flag in SuspendedFrame so the trampoline skips its datastack release (the caller owns that cleanup) - Clear iframe.previous in exit_iframe before unlinking the chain, matching with_frame and resume_gen_frame behavior - Add scopeguard in with_iframe for panic safety - Use saturating_sub(1) for lasti in trampoline_handle_exception - Extract datastack_iframe_localsplus_offset helper to avoid duplicated alignment computation Assisted-by: Claude
I left one lint (a clippy deny) unfixed because it's a lot more involved, so I'll work on it in a different patch.
The cell type filled neither the richcompare nor the repr slot, so object's address-based defaults showed through: cell(1) == cell(1) was False, ordering raised TypeError, and repr rendered <cell object at 0x...> rather than <cell at 0x...: int object at 0x...>. Compare cells by contents, with empty cells ordering before everything else, and render CPython's repr for both the filled and empty cases. The comparison fills the richcompare slot directly rather than going through Comparable, whose cmp() can only answer with a bool. CPython returns whatever PyObject_RichCompare produced, so a contained __eq__ that yields a non-bool must pass through untouched; coercing it would also call __bool__ and surface exceptions CPython never raises. The empty-cell branch still answers with a bool, so both arms are needed and the slot returns Either. The repr truncates the contained type name the way "%.80s" does: at most 80 bytes, dropping a character the cut would leave incomplete. Mark the type unhashable. Content-based equality combined with the inherited identity hash would break the hash/eq contract, and hashing the contents is not possible either because cell_contents is writable. CPython gets this implicitly, because defining tp_richcompare suppresses tp_hash inheritance. Reference: CPython Objects/cellobject.c, cell_richcompare and cell_repr. Assisted-by: Claude Code:claude-opus-5
…8464) * Use type-specialized comparators for homogeneous list sorts Scan the sort keys once before sorting; when every element is exactly str, int, or float, compare wtf8 bytes / BigInt / f64 directly instead of going through rich_compare_bool dispatch, mirroring CPython's pre-sort check in listsort.c (unsafe_latin_compare and friends). Subclasses and mixed-type lists keep the generic __lt__ path. * Add edge-case tests for specialized list sorts * Cache the richcompare slot for homogeneous list sorts * Specialize tuple sorts on their first elements * Apply ruff formatting to the new list sort tests * Deduplicate the reverse swap across sort dispatch arms
…tside function scope (RustPython#8467) CPython's _PyFrame_GetLocals only syncs fastlocals/cells into locals() for function scope; module/class scope just returns the namespace dict as-is. sync_visible_locals_to_mapping did this for every scope, so the implicit __conditional_annotations__ cell (used for PEP 649/749 deferred annotations) broke two ways: at module scope its cell is always empty, so syncing overwrote the dict's real value with None, causing NameError on the next annotated statement; at class scope its cell is the only real value, so syncing leaked it into locals()/dir(), unlike CPython. Skip cell/free slots outside function scope to match CPython, and add a regression snippet. Closes RustPython#8379 Assisted-by: Claude Code:claude-sonnet-5
) * Allow automated commits through pre-commit hooks * Fix agent C-API test instructions Exclude rustpython-capi from root workspace test commands and run its tests from the crate directory so its Cargo configuration applies. Document the project AI policy and required commit trailer. Assisted-by: Codex:gpt-5
According to POSIX, `time_t` should be 64 bits. `musl` changed its `time_t` to an `i64` over five years ago. `glibc` provides compatibility features that declare `time_t` as either `i32` or `i64`. Rustix uses the raw Linux syscall for stat which returns an `i64`. For our purposes, an `i64` makes sense because it's modern and avoids the year 2038 problem. It also reduces our dependency on what `libc` defines. Sources: * https://www.man7.org/linux/man-pages/man3/time_t.3type.html * https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_types.h.html
…prefix (RustPython#8473) `search_info_literal`'s len>1 arm reset the tail-match cursor by advancing one character past the matched prefix. That position equals the INFO block's prefix_skip boundary only when the prefix ends where the skip does; for a pattern like `ab(cd)`, `_get_literal_prefix` reports prefix_len=4 with prefix_skip=2, so the tail resumed two characters too far. `state.cursor` already holds `req.start + skip`, which is what `sre_lib.h` SRE(search) computes as `ptr - (prefix_len - prefix_skip - 1)`, and which the len==1 arm above already uses. Take it unconditionally. Searching "xabcdcd" for `ab(cd)` returned span (1, 7) instead of (1, 5); over a 600-case corpus stamped with CPython's own answers, 94 cases disagreed before this change and none after. The wrong resume also dropped matches outright, not only widened them. Assisted-by: Claude
Assisted-by: Codex:gpt-5
* Fix EOF SyntaxError diagnostics * Fix Scope EOF SyntaxError location conversion * Fix Additional Unexpected Test * Docs Add Annotation source_location_in_code_points()
code.replace() called as_interned_str().unwrap() on its string arguments, which panics when the caller passes a string that has not been interned. modulefinder's replace_paths_in_code() builds a fresh co_filename, so any use of ModuleFinder(replace_paths=...) aborted the interpreter. Intern the incoming strings instead, and raise TypeError rather than panicking when a non-string appears in co_names/co_varnames/ co_cellvars/co_freevars. Unskips test_modulefinder.test_replace_paths. Co-authored-by: Pablo Garcia <[email protected]>
Rust supports C string literals which automatically create a CStr with a trailing NUL. `windows-sys` provides an analogous macro for wide strings. Both of these avoid allocations which is nice for constants.
Part of: RustPython#4583 This will enable -m test for wasi preview 1 Signed-off-by: Jiwoo Ahn <[email protected]>
Assisted-by: Codex:gpt-5.6-sol
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThe change adds a shared VM-aware format-spec parser. Boolean, complex, float, integer, and string formatting methods now use it for parsing and error conversion. ChangesFormat-spec parsing
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] test: cpython/Lib/test/test_format.py dependencies: dependent tests: (no tests depend on format) [x] lib: cpython/Lib/ssl.py dependencies:
dependent tests: (53 tests)
Legend:
|
let me think once again if this is the best way
youknowone
left a comment
There was a problem hiding this comment.
Hi! I left a change request not to make confusion to old path.
Sorry for late review!
| } | ||
| } | ||
|
|
||
| pub(crate) fn parse_format_spec( |
There was a problem hiding this comment.
due to this helper, FormatSpecError::InvalidFormatSpecifier arm in impl IntoPyException for FormatSpecError is now a trap. The error message will be diverged by its calling path.
if we go this direction, I prefer to remove impl IntoPyException for FormatSpecError and bring the implementation into this helper.
Summary
This is a follow-up to #8475. RustPython still returned the generic
Invalid format specifiermessage for malformed format specifications, while CPython includes both the original specifier and the runtime object type.Add a VM-level format-spec parsing helper that maps only
InvalidFormatSpecifierto CPython's detailedValueErrormessage. Integer, boolean, float, complex, and string formatting now use the helper, including subclasses whose runtime type names must appear in the error.With the error text matching CPython, this enables the existing
test_better_error_message_format,test_unicode_in_error_message, andtest_specifier_z_errortests without changing their assertions or test data.Tests
cargo run --release -- -m test test_formatcargo test --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher --exclude rustpython-capi(cd crates/capi && cargo test)— 102 passedcargo clippy --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher --all-targetsAI assistance
Codex (GPT-5.6) assisted with comparing CPython and RustPython error behavior, implementing the shared parsing helper, enabling the existing regression tests, running validation, and drafting this PR description. I reviewed the final diff and verified the behavior locally on macOS.
Summary by CodeRabbit