Add basic capi error support by bschoenmaeckers · Pull Request #7787 · RustPython/RustPython
Note
Reviews paused
It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.
Use the following commands to manage reviews:
@coderabbitai resumeto resume automatic reviews.@coderabbitai reviewto trigger a single review.
Use the checkboxes below for quick actions:
-
▶️ Resume reviews - 🔍 Trigger review
📝 Walkthrough
Walkthrough
Initializes and exposes C-API exception statics and object/type helpers, adds FFI result conversions and a with_vm helper, makes VM exception APIs public, registers the main interpreter via set_main_interpreter, and wires/tests C-API exception handling and CI test steps.
Changes
C‑API Exception & Object Bridge
| Layer / File(s) | Summary |
|---|---|
Data Shape / Statics crates/capi/src/pyerrors.rs |
Adds define_exception_statics! and many #[unsafe(no_mangle)] pub static mut ...: *mut PyObject; introduces pub(crate) unsafe fn init_exception_statics(zoo: &'static ExceptionZoo). |
FFI Result Conversion crates/capi/src/util.rs |
Adds pub(crate) trait FfiResult<Output=Self> with ERR_VALUE and into_output(self, vm); implements conversions for pointers, numerics, bools, floats, usize->isize, and PyResult<T> that set VM exceptions on error. |
VM Surface / Visibility crates/vm/src/vm/mod.rs, crates/vm/src/builtins/type.rs |
Promotes VirtualMachine::current_exception and set_exception to pub; adds pub fn take_raised_exception(&self) -> Option<PyBaseExceptionRef>; makes Py<PyType>::is_subtype public. |
FFI Function Layer crates/capi/src/pyerrors.rs, crates/capi/src/pystate.rs |
Implements PyErr_* FFI functions (PyErr_Occurred, PyErr_GetRaisedException, PyErr_SetRaisedException, PyErr_SetObject, PyErr_SetString, PyErr_PrintEx, PyErr_DisplayException, PyErr_WriteUnraisable, PyErr_NewException, PyErr_NewExceptionWithDoc, PyErr_GivenExceptionMatches) using with_vm; adds PyEval_RestoreThread stub. |
Initialization / Wiring crates/capi/src/lib.rs, crates/capi/src/pylifecycle.rs, src/lib.rs |
Adds pub fn set_main_interpreter(interpreter: Interpreter) that asserts unset, calls unsafe init_exception_statics(&Context::genesis().exceptions), and stores the interpreter; Py_InitializeEx also calls init_exception_statics before creating the interpreter; run() now calls rustpython_capi::set_main_interpreter(interp). |
Object helpers / Constants crates/capi/src/object.rs |
Adds pub type PyTypeObject = Py<PyType> and C-ABI functions Py_TYPE, Py_IS_TYPE, PyType_GetFlags, and Py_GetConstantBorrowed. |
Tests / Misc / CI / Manifest crates/capi/src/pyerrors.rs, .cspell.dict/cpython.txt, .github/workflows/ci.yaml, Cargo.toml |
Adds unit tests for raised exceptions and type checks; adds pyerrors to cspell; excludes rustpython-capi from workspace tests and adds dedicated CI step to run crates/capi tests; switches workspace pyo3 dependency to the PyO3 git repository. |
Sequence Diagram
sequenceDiagram
participant C as C caller
participant CApi as rustpython-capi
participant VM as VirtualMachine
participant Exc as ExceptionStack
C->>CApi: PyErr_SetObject(exc_type, value)
CApi->>VM: with_vm -> &VirtualMachine
VM->>VM: normalize_exception(type, value) -> PyBaseExceptionRef
VM-->>CApi: PyBaseExceptionRef
CApi->>Exc: vm.set_exception(Some(exc))
C->>CApi: PyErr_Occurred()
CApi->>VM: with_vm -> vm.current_exception()
VM-->>CApi: Option<PyBaseExceptionRef>
CApi-->>C: *mut PyObject or NULL
C->>CApi: PyErr_GetRaisedException()
CApi->>VM: with_vm -> vm.take_raised_exception()
VM-->>CApi: Option<PyBaseExceptionRef>
CApi-->>C: *mut PyObject or NULL
C->>CApi: PyErr_PrintEx()
CApi->>VM: with_vm -> vm.take_raised_exception()
VM->>VM: print_exception(exc)
VM-->>CApi: done
Estimated Code Review Effort
🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly Related PRs
- RustPython/RustPython#7648: Introduced C-API lifecycle groundwork (MAIN_INTERP / pylifecycle) that this change builds upon.
Suggested Reviewers
- youknowone
Poem
🐰
I hopped through statics, pointers, and thread,
I bridged PyErrs from C into the VM bed.
With careful paws and tiny leaps,
Exceptions wake from borrowed sleeps.
A carrot for tests — may reviews be sped.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 58.14% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The PR title 'Add basic capi error support' accurately describes the primary changes, which comprehensively add C-API error handling infrastructure including exception statics, FFI functions, and utilities. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
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 @coderabbitai help to get the list of available commands and usage tips.