Add c-api error handling#7784
Conversation
📝 WalkthroughWalkthroughThis PR introduces a Rust-to-C FFI binding layer ( ChangesC-API Layer Integration
Sequence DiagramsequenceDiagram
participant Client as External C Code
participant API as RustPython C-API
participant Interp as Interpreter<br/>(MAIN_INTERP)
participant VM as VirtualMachine
participant Exc as Exception Stack
Client->>API: Py_Initialize()
API->>Interp: create & store MAIN_INTERP
Interp->>VM: Interpreter::with_init()
Interp->>VM: ensure_thread_has_vm_attached()
Client->>API: PyGILState_Ensure()
API->>VM: attach_current_thread()
VM-->>API: return attached state
Client->>API: PyErr_SetString(PyExc_TypeError, msg)
API->>Exc: set exception in VM
Exc-->>API: exception stored
Client->>API: PyErr_Occurred()
Exc-->>API: return exception ptr
Client->>API: PyGILState_Release(state)
API->>VM: release_current_thread()
VM-->>API: detached
Client->>API: Py_FinalizeEx()
API->>Interp: finalize main interpreter
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly Related PRs
Suggested Reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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 |
Sorry, something went wrong.
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/vm/src/object/core.rs (1)
477-503: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick winGate narrowing on
reset_weakref_locks_after_forkbreaks its call site inposix.rs::py_os_after_fork_child
reset_weakref_locks_after_fork(line 500) is now compiled only underunix + threading + host_env, but its call site incrates/vm/src/stdlib/posix.rs::py_os_after_fork_child(line ~791) is gated only on#[cfg(feature = "threading")](andposix.rsis Unix-only, making it effectivelyunix + threading). Builds withunix + threadingbut withouthost_envwill fail to compile there.The call in
posix.rs:#[cfg(feature = "threading")] crate::object::reset_weakref_locks_after_fork();needs to become:
#[cfg(all(feature = "threading", feature = "host_env"))] crate::object::reset_weakref_locks_after_fork();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/vm/src/object/core.rs` around lines 477 - 503, The call site gating for reset_weakref_locks_after_fork in posix.rs::py_os_after_fork_child must match the function's cfg; change the cfg on the call to require both feature = "threading" and feature = "host_env" (i.e. use #[cfg(all(feature = "threading", feature = "host_env"))]) so the call to crate::object::reset_weakref_locks_after_fork() is only compiled when the function is present.crates/vm/src/vm/mod.rs (1)
2063-2098: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftBack C-API exception functions with a separate error-indicator state, not the handled-exception stack.
Currently,
PyErr_Occurred()andPyErr_GetRaisedException()read from the same stack that backssys.exc_info()and generatorgi_exc_state(theexc_infoslot managed byPUSH_EXC_INFO/POP_EXCEPT). According to CPython semantics, these C-API functions should operate on the per-thread "error indicator" state—representing exceptions still propagating between C calls—which is distinct from and independent of the handled-exception state. Using theexc_infostack causes:
- C-API code can observe exceptions caught by Python
try/except, which should be invisible at the C level.- Calling
PyErr_GetRaisedException()+PyErr_SetRaisedException()can corrupt the active exception state of the current frame or generator.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/vm/src/vm/mod.rs` around lines 2063 - 2098, The C-API error-indicator must be backed by a separate per-Vm state, not the exc_info stack used by sys.exc_info()/PUSH_EXC_INFO; change the methods so they don't read/write exceptions.stack: leave current_exception/set_exception (and their semantics for the exc_info stack) as-is, and introduce/replace the C-API facing API with a separate storage (e.g., add a new field like raised_exception: RefCell<Option<PyBaseExceptionRef>>) and implement get_raised_exception / set_raised_exception / take_raised_exception to operate on that field instead of exceptions.stack; ensure thread::update_thread_exception continues to reflect the thread-visible error indicator using the new getter (not topmost_exception), and update any callers that relied on the old take_raised_exception to use the new C-API methods so C-level errors do not corrupt the handled-exception stack.
🧹 Nitpick comments (5)
crates/capi/src/pystate.rs (1)
11-13: 💤 Low valueCaveat for future callers of
with_vm.
with_current_vmholds aRefCellborrow onVM_STACKfor the duration of the callback (percrates/vm/src/vm/thread.rs:88-99). Iffever transitively callsrelease_current_threador anything that tries to mutateVM_STACK, it will hit aborrow_mutpanic. None of today's call sites do that, but a brief safety comment onwith_vmwould prevent future footguns.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/capi/src/pystate.rs` around lines 11 - 13, with_vm currently calls with_current_vm which holds a RefCell borrow on VM_STACK for the duration of the callback; if the provided closure f (or anything it transitively calls) tries to mutate VM_STACK (for example by calling release_current_thread) it will cause a borrow_mut panic — add a concise safety comment on with_vm explaining that the closure must not call any function that mutates or re-enters VM_STACK (e.g., release_current_thread or other VM stack-mutating APIs) and suggest using a different API or refactoring to avoid holding the borrow across such calls; reference the functions with_vm and with_current_vm and the VM_STACK cell in the comment to help future callers locate the caveat.crates/capi/src/util.rs (1)
79-85: 💤 Low value
usize → isizecast can produce a spurious error sentinel.
self as isizewraps whenself > isize::MAX, which would silently turn a very large length into a negative value indistinguishable fromERR_VALUE = -1. For sizes returned by C-API functions (e.g.,Py_ssize_t-shaped APIs) this is unlikely in practice, but considerisize::try_from(self).unwrap_or(isize::MAX)or asserting the upper bound, or at minimum a comment documenting the assumption.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/capi/src/util.rs` around lines 79 - 85, The impl FfiResult<isize> for usize currently casts usize -> isize in into_output which can wrap for values > isize::MAX and collide with ERR_VALUE; change into_output in the impl for usize to convert safely (e.g., use isize::try_from(self).unwrap_or(isize::MAX) or otherwise saturate/validate and return isize::MAX on overflow) and document the chosen behavior, making sure ERR_VALUE (-1) remains distinct; update the impl block (symbols: FfiResult<isize> for usize, const ERR_VALUE, fn into_output(self, _vm: &VirtualMachine)) accordingly.crates/capi/src/object.rs (1)
70-83: ⚡ Quick winReplace
panic!with CPython-conventional error.A
panic!in anextern "C"function aborts the process (since Rust 1.81 panics across the FFI boundary unwind into an abort). CPython'sPy_GetConstant/Py_GetConstantBorrowedconventionally raiseSystemErrorand returnNULLon an invalid id, which is friendlier and matches what C-extension authors expect.♻️ Suggested change
-pub extern "C" fn Py_GetConstantBorrowed(constant_id: c_uint) -> *mut PyObject { - with_vm(|vm| { - let ctx = &vm.ctx; - match constant_id { - 0 => ctx.none.as_object(), - 1 => ctx.false_value.as_object(), - 2 => ctx.true_value.as_object(), - 3 => ctx.ellipsis.as_object(), - 4 => ctx.not_implemented.as_object(), - _ => panic!("Invalid constant_id passed to Py_GetConstantBorrowed"), - } - .as_raw() - }) -} +pub extern "C" fn Py_GetConstantBorrowed(constant_id: c_uint) -> *mut PyObject { + with_vm(|vm| -> PyResult<PyObjectRef> { + let ctx = &vm.ctx; + let obj = match constant_id { + 0 => ctx.none.as_object(), + 1 => ctx.false_value.as_object(), + 2 => ctx.true_value.as_object(), + 3 => ctx.ellipsis.as_object(), + 4 => ctx.not_implemented.as_object(), + _ => return Err(vm.new_system_error(format!( + "Py_GetConstantBorrowed: invalid constant_id {constant_id}" + ))), + }; + Ok(obj.to_owned()) + }) +}(Or, if the
as_raw/borrowed-pointer semantics need to be preserved exactly, return*mut PyObjectdirectly viaFfiResultand set the exception inline, returningnull_mut()on the bad-id path.)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/capi/src/object.rs` around lines 70 - 83, In Py_GetConstantBorrowed replace the panic! on the _ (invalid id) branch with CPython-style behavior: create/raise a SystemError on the VM/context (e.g. via vm.ctx.new_system_error(...) or the crate's VM exception-raising helper) and return null_mut() from the extern "C" function; alternatively, change the function to return an FfiResult that sets the exception and yields a null pointer on error. Ensure you still return the borrowed object's as_raw() for valid ids and do not unwind across the FFI boundary.crates/capi/src/lib.rs (1)
27-33: 💤 Low value
Context::genesis()is reused; verify it matches the interpreter's context.
init_exception_statics(&Context::genesis().exceptions)initializes exception statics from the genesis context, while the storedinterpretermay have been built with its ownContext. Todaygenesis()is effectively a global singleton in RustPython so this works, but ifContextever becomes per-interpreter, the statics here will diverge from the interpreter actually serving C-API calls. Consider deriving the exceptions from the interpreter being installed (e.g.,interpreter.enter(|vm| init_exception_statics(&vm.ctx.exceptions))before storing) so the wiring stays correct under future refactors.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/capi/src/lib.rs` around lines 27 - 33, The code currently calls init_exception_statics(&Context::genesis().exceptions) which may diverge if Context becomes per-interpreter; change set_main_interpreter to derive exceptions from the Interpreter being installed by entering the interpreter (e.g., use Interpreter::enter or interpreter.enter(|vm| ...)) and call init_exception_statics(&vm.ctx.exceptions) while still in that closure, then store the interpreter; ensure the safety comment is updated to reflect that exception statics are initialized from the interpreter's Context and keep the assert!(interp.is_none()) and assignment to *interp = Some(interpreter) as before.build.rs (1)
5-12: 💤 Low valueWindows +
capihas no symbol-export configuration.When
target == "windows" && capi_enabled, the binary won't export the C-API symbols (no--export-all-symbols, no.deffile, no__declspec(dllexport)on the Rust side). Linux/macOS get-Wl,--export-dynamic/-Wl,-export_dynamic, but Windows binaries need explicit export markup to be loadable as a Python host by C extensions. If Windows support forcapiis intended, consider emitting an equivalent flag or.deffile; if it's deliberately deferred, a comment here documenting that would help.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@build.rs` around lines 5 - 12, The Windows branch currently lacks any export configuration when target.as_str() == "windows" and capi_enabled is true; update the build.rs match to handle that case by either (a) generating a module-definition (.def) file listing the C-API symbols and emitting a cargo:rustc-link-arg-bin=rustpython=/DEF:<path> (or rustc-link-arg for the MSVC linker) or (b) detecting MinGW and emitting the appropriate -Wl,--export-all-symbols flag; implement one of these in the "windows" arm and add a brief comment that documents which method you chose and why (reference the target.as_str() match, the capi_enabled flag, and the println! calls that emit cargo:rustc-link-arg-bin).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/capi/.cargo/config.toml`:
- Around line 1-3: The PYO3 env entries (PYO3_CONFIG_FILE and PYO3_NO_PYTHON)
defined in the local crate .cargo/config.toml won't be picked up for
workspace-root builds; move those two entries into the workspace root
.cargo/config.toml, keep PYO3_CONFIG_FILE pointed at pyo3-rustpython.config (do
not change it to ../pyo3-rustpython.config since relative=true already resolves
to the crate dir), and remove the duplicate/local config so workspace builds
(e.g., builds with the capi feature) inherit the PYO3 settings.
In `@crates/capi/src/object.rs`:
- Around line 32-67: PyType_GetFlags currently initializes flags from
ty.slots.flags.bits() (u64) and then ORs c_ulong constants
(PY_TPFLAGS_LONG_SUBCLASS, etc.), which breaks on Windows because c_ulong is
u32; fix by casting the initial value to c_ulong—i.e., change the initialization
of flags in PyType_GetFlags so it uses ty.slots.flags.bits() as c_ulong before
any |= with the PY_TPFLAGS_* constants so all operations are the same c_ulong
type.
In `@crates/capi/src/pyerrors.rs`:
- Around line 99-105: PyErr_Occurred currently returns the exception instance
(exc.as_object().as_raw()) but must return the exception type (the first arg to
PyErr_Set*), so change the mapper in PyErr_Occurred to return the exception's
type raw pointer instead — i.e., when vm.current_exception() yields exc, return
the raw pointer for exc's class/type (use the VM/exception API such as
exc.class().as_object().as_raw() or the equivalent on your exception type) and
keep the borrowed semantics (no INCREF), preserving the unwrap_or_default
fallback.
- Around line 118-123: In PyErr_SetRaisedException, validate the incoming
pointer before taking ownership: check that exc is not null (use NonNull::new
instead of NonNull::new_unchecked and return an appropriate Err if null), then
construct the PyObjectRef via PyObjectRef::from_raw only after the non-null
check, and replace downcast_unchecked() with a checked downcast (e.g.,
downcast() or the crate's checked variant) so you verify the object is an
exception instance before returning Err(exception).
- Around line 192-236: The extern "C" functions (notably PyErr_NewException,
PyErr_NewExceptionWithDoc, PyErr_PrintEx, PyErr_DisplayException,
PyErr_WriteUnraisable) currently call expect!/panic!/assert!, which will abort
the process on bad input; instead catch invalid inputs, set a Python SystemError
on the VM and return NULL (or return early) per the C-API contract. Replace uses
of expect()/panic!/assert! in PyErr_NewException (e.g.,
CStr::from_ptr(...).to_str().expect(...), rsplit_once().expect(...), panic! for
bad base types, and assert! on dict) with guarded checks that build an error
message, call vm.ctx.exceptions.system_error (or
vm.set_exception(vm.ctx.exceptions.system_error, message)) to set the exception
on the VM, and then return std::ptr::null_mut(); apply the same pattern to
PyErr_NewExceptionWithDoc (delegate should propagate NULL on error) and to
PyErr_PrintEx / PyErr_DisplayException / PyErr_WriteUnraisable so they no longer
panic but set an appropriate SystemError and return gracefully.
In `@crates/capi/src/pylifecycle.rs`:
- Around line 42-53: Py_FinalizeEx() currently returns success without resetting
interpreter state; update Py_FinalizeEx to properly finalize and clear
MAIN_INTERP (drop/free the interpreter handle and set MAIN_INTERP to null/None)
and update whatever initialized flag Py_IsInitialized() checks so it returns 0
after finalize; ensure Py_Finalize() still calls Py_FinalizeEx(), and mirror the
same teardown in Py_FinalizeEx so a subsequent Py_InitializeEx() can create a
fresh interpreter. Reference: Py_FinalizeEx, Py_Finalize, MAIN_INTERP,
Py_IsInitialized, Py_InitializeEx.
In `@crates/capi/src/pystate.rs`:
- Around line 46-49: The PyEval_SaveThread stub must not silently return NULL;
update the body of the extern "C" function PyEval_SaveThread to fail loudly
instead of ptr::null_mut(): add a TODO comment about implementing proper GIL
release, and replace the current return with either an explicit abort (print a
clear message then process::abort()) or call unimplemented!() so callers (and C
extensions expecting a valid PyThreadState pointer) will fail loudly during
development; also ensure the complementary PyEval_RestoreThread handling is
noted in the TODO so the full pair gets implemented against
release_current_thread/attach_current_thread later.
In `@crates/vm/src/codecs.rs`:
- Around line 161-164: The cfg gates are inconsistent:
CodecsRegistry::reinit_after_fork and StringPool::reinit_after_fork are only
defined with #[cfg(all(unix, feature = "threading", feature = "host_env"))] but
posix::reinit_locks_after_fork (posix.rs::reinit_locks_after_fork) is gated with
#[cfg(all(unix, feature = "threading"))], causing missing method errors when
host_env is disabled; update the cfg on posix::reinit_locks_after_fork to
#[cfg(all(unix, feature = "threading", feature = "host_env"))] so its calls to
CodecsRegistry::reinit_after_fork and StringPool::reinit_after_fork compile
consistently.
In `@crates/vm/src/intern.rs`:
- Around line 39-42: The function reinit_locks_after_fork is currently gated
with #[cfg(all(unix, feature = "threading"))] but calls
StringPool::reinit_after_fork and CodecRegistry::reinit_after_fork which are
defined only when #[cfg(all(unix, feature = "threading", feature = "host_env"))]
is set; change the attribute on reinit_locks_after_fork to #[cfg(all(unix,
feature = "threading", feature = "host_env"))] so the compilation gate matches
the methods it calls (locate the reinit_locks_after_fork function and update its
cfg to include feature = "host_env").
In `@crates/vm/src/stdlib/_io.rs`:
- Around line 5-6: The exported function cfg is too restrictive: change the
module-level export so reinit_std_streams_after_fork and reinit_io_locks are
available under #[cfg(all(unix, feature = "threading"))] and move the
#[cfg(feature = "host_env")] guard inside each function body; implement the
host_env-disabled path as a no-op (early return) so calls from posix.rs (which
are under #[cfg(feature = "threading")]) compile when host_env is not enabled,
while keeping the real implementation when host_env is present.
In `@crates/vm/src/stdlib/_thread.rs`:
- Around line 2-3: The call site py_os_after_fork_child in posix.rs calls
after_fork_child which is only exported under #[cfg(all(unix, feature =
"threading", feature = "host_env"))]; update the gating around
py_os_after_fork_child (or the specific call) to require the same cfg (e.g.
#[cfg(all(unix, feature = "threading", feature = "host_env"))]) so the call is
only compiled when after_fork_child is available, ensuring the cfg for
py_os_after_fork_child matches the after_fork_child export.
In `@crates/vm/src/vm/thread.rs`:
- Around line 175-190: The release_current_thread function currently drops
GILSTATE_VM before popping the raw pointer from VM_STACK, which can cause
destructors to call with_current_vm and dereference freed memory; fix by
reversing the order in release_current_thread: first remove/pop the VM pointer
from VM_STACK (the vms.borrow_mut().pop().expect(...) call) and only after that
take/drop the GILSTATE_VM (GILSTATE_VM.with(|gilstate_vm|
gilstate_vm.borrow_mut().take())); keep the existing detach_thread call and
other logic unchanged.
---
Outside diff comments:
In `@crates/vm/src/object/core.rs`:
- Around line 477-503: The call site gating for reset_weakref_locks_after_fork
in posix.rs::py_os_after_fork_child must match the function's cfg; change the
cfg on the call to require both feature = "threading" and feature = "host_env"
(i.e. use #[cfg(all(feature = "threading", feature = "host_env"))]) so the call
to crate::object::reset_weakref_locks_after_fork() is only compiled when the
function is present.
In `@crates/vm/src/vm/mod.rs`:
- Around line 2063-2098: The C-API error-indicator must be backed by a separate
per-Vm state, not the exc_info stack used by sys.exc_info()/PUSH_EXC_INFO;
change the methods so they don't read/write exceptions.stack: leave
current_exception/set_exception (and their semantics for the exc_info stack)
as-is, and introduce/replace the C-API facing API with a separate storage (e.g.,
add a new field like raised_exception: RefCell<Option<PyBaseExceptionRef>>) and
implement get_raised_exception / set_raised_exception / take_raised_exception to
operate on that field instead of exceptions.stack; ensure
thread::update_thread_exception continues to reflect the thread-visible error
indicator using the new getter (not topmost_exception), and update any callers
that relied on the old take_raised_exception to use the new C-API methods so
C-level errors do not corrupt the handled-exception stack.
---
Nitpick comments:
In `@build.rs`:
- Around line 5-12: The Windows branch currently lacks any export configuration
when target.as_str() == "windows" and capi_enabled is true; update the build.rs
match to handle that case by either (a) generating a module-definition (.def)
file listing the C-API symbols and emitting a
cargo:rustc-link-arg-bin=rustpython=/DEF:<path> (or rustc-link-arg for the MSVC
linker) or (b) detecting MinGW and emitting the appropriate
-Wl,--export-all-symbols flag; implement one of these in the "windows" arm and
add a brief comment that documents which method you chose and why (reference the
target.as_str() match, the capi_enabled flag, and the println! calls that emit
cargo:rustc-link-arg-bin).
In `@crates/capi/src/lib.rs`:
- Around line 27-33: The code currently calls
init_exception_statics(&Context::genesis().exceptions) which may diverge if
Context becomes per-interpreter; change set_main_interpreter to derive
exceptions from the Interpreter being installed by entering the interpreter
(e.g., use Interpreter::enter or interpreter.enter(|vm| ...)) and call
init_exception_statics(&vm.ctx.exceptions) while still in that closure, then
store the interpreter; ensure the safety comment is updated to reflect that
exception statics are initialized from the interpreter's Context and keep the
assert!(interp.is_none()) and assignment to *interp = Some(interpreter) as
before.
In `@crates/capi/src/object.rs`:
- Around line 70-83: In Py_GetConstantBorrowed replace the panic! on the _
(invalid id) branch with CPython-style behavior: create/raise a SystemError on
the VM/context (e.g. via vm.ctx.new_system_error(...) or the crate's VM
exception-raising helper) and return null_mut() from the extern "C" function;
alternatively, change the function to return an FfiResult that sets the
exception and yields a null pointer on error. Ensure you still return the
borrowed object's as_raw() for valid ids and do not unwind across the FFI
boundary.
In `@crates/capi/src/pystate.rs`:
- Around line 11-13: with_vm currently calls with_current_vm which holds a
RefCell borrow on VM_STACK for the duration of the callback; if the provided
closure f (or anything it transitively calls) tries to mutate VM_STACK (for
example by calling release_current_thread) it will cause a borrow_mut panic —
add a concise safety comment on with_vm explaining that the closure must not
call any function that mutates or re-enters VM_STACK (e.g.,
release_current_thread or other VM stack-mutating APIs) and suggest using a
different API or refactoring to avoid holding the borrow across such calls;
reference the functions with_vm and with_current_vm and the VM_STACK cell in the
comment to help future callers locate the caveat.
In `@crates/capi/src/util.rs`:
- Around line 79-85: The impl FfiResult<isize> for usize currently casts usize
-> isize in into_output which can wrap for values > isize::MAX and collide with
ERR_VALUE; change into_output in the impl for usize to convert safely (e.g., use
isize::try_from(self).unwrap_or(isize::MAX) or otherwise saturate/validate and
return isize::MAX on overflow) and document the chosen behavior, making sure
ERR_VALUE (-1) remains distinct; update the impl block (symbols:
FfiResult<isize> for usize, const ERR_VALUE, fn into_output(self, _vm:
&VirtualMachine)) accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 7a69f801-df68-4089-9da5-e5695cac77a4
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (25)
.cspell.dict/cpython.txt.cspell.dict/python-more.txtCargo.tomlbuild.rscrates/capi/.cargo/config.tomlcrates/capi/Cargo.tomlcrates/capi/pyo3-rustpython.configcrates/capi/src/lib.rscrates/capi/src/object.rscrates/capi/src/pyerrors.rscrates/capi/src/pylifecycle.rscrates/capi/src/pystate.rscrates/capi/src/refcount.rscrates/capi/src/util.rscrates/vm/Cargo.tomlcrates/vm/src/builtins/type.rscrates/vm/src/codecs.rscrates/vm/src/intern.rscrates/vm/src/object/core.rscrates/vm/src/stdlib/_imp.rscrates/vm/src/stdlib/_io.rscrates/vm/src/stdlib/_thread.rscrates/vm/src/vm/mod.rscrates/vm/src/vm/thread.rssrc/lib.rs
💤 Files with no reviewable changes (1)
- crates/vm/Cargo.toml
Sorry, something went wrong.
This is the next step in adding c-api support. It also contains utilities to handle errors for implementing other c-api functions.
Summary by CodeRabbit
New Features
Refactor
Chores