Skip to content

Add more c-api error functions#7915

Open
bschoenmaeckers wants to merge 2 commits into
RustPython:mainfrom
bschoenmaeckers:c-api-more-err
Open

Add more c-api error functions#7915
bschoenmaeckers wants to merge 2 commits into
RustPython:mainfrom
bschoenmaeckers:c-api-more-err

Conversation

@bschoenmaeckers
Copy link
Copy Markdown
Contributor

@bschoenmaeckers bschoenmaeckers commented May 18, 2026

Summary by CodeRabbit

  • New Features
    • C API to inspect exceptions: check exception classes and access an exception's traceback, cause, and context.
    • C API support for traceback handling: type checking and printing formatted tracebacks to a file-like object.
    • Traceback module made publicly available to C API consumers.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 32073fb1-a88b-49f0-b4fe-29d63ab33259

📥 Commits

Reviewing files that changed from the base of the PR and between 737ad27 and 7bda56a.

📒 Files selected for processing (3)
  • crates/capi/src/lib.rs
  • crates/capi/src/pyerrors.rs
  • crates/capi/src/traceback.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/capi/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/capi/src/pyerrors.rs
  • crates/capi/src/traceback.rs

📝 Walkthrough

Walkthrough

This PR adds C-API predicates and getters for exception inspection, an FFI binding PyTraceBack_Print that calls Python's traceback.print_tb inside the VM, and re-exports the traceback module from the crates/capi crate root.

Changes

Exception and Traceback C-API Bindings

Layer / File(s) Summary
Exception inspection C-API
crates/capi/src/pyerrors.rs
Imports define_py_check, exports PyExceptionInstance_Check, adds PyExceptionClass_Check to test exception classes for subtype relationship, and implements PyException_GetTraceback, PyException_GetCause, and PyException_GetContext returning raw PyObject* or null.
Traceback printing binding
crates/capi/src/traceback.rs
Defines PyTraceBack_Check predicate and implements pub unsafe extern "C" fn PyTraceBack_Print(tb, file) -> c_int which enters the VM, imports traceback, and calls print_tb(tb, file=...).
Traceback module export
crates/capi/src/lib.rs
Adds pub mod traceback; to expose the traceback binding module from the crate root.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • youknowone

Poem

🐰 With paws on keys and whiskers bright,
I call print_tb into the night.
Exceptions scanned and tracebacks shown,
The C-API sings in careful tone.
Hoppity hop — the bindings grown.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title describes the addition of C-API error functions, which is partially reflected in the changeset. However, the changes also include traceback functionality (new traceback module export and PyTraceBack_Print), which goes beyond just error functions and is not mentioned in the title.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/capi/src/traceback.rs (1)

10-13: 💤 Low value

Consider null pointer checks for defensive safety.

While this is an unsafe extern "C" function, dereferencing tb and file without null checks at lines 12-13 will cause undefined behavior if callers pass null. A defensive check could improve robustness:

🛡️ Optional defensive null check
 pub unsafe extern "C" fn PyTraceBack_Print(tb: *mut PyObject, file: *mut PyObject) -> c_int {
+    if tb.is_null() || file.is_null() {
+        return -1;
+    }
     with_vm(|vm| {
         let tb = unsafe { &*tb };
         let file = unsafe { &*file };
🤖 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/traceback.rs` around lines 10 - 13, The function
PyTraceBack_Print currently dereferences tb and file unsafely; add null-pointer
checks for the incoming raw pointers (tb and file) before the unsafe
dereferences inside PyTraceBack_Print (the locations where it does let tb = &*tb
and let file = &*file) and return an appropriate c_int error value (e.g., -1) if
either is null (and optionally set a Python C-API error), otherwise proceed into
with_vm as before.
🤖 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/src/pyerrors.rs`:
- Around line 290-297: PyException_GetContext currently returns Py_None when no
context is set (via vm.unwrap_or_none(context)), but CPython semantics and the
tests expect a NULL pointer; update PyException_GetContext to mirror the style
used in PyException_GetCause/PyException_GetTraceback by converting the optional
context to a raw pointer and returning null when absent (e.g., map the Option to
either the object's raw pointer or std::ptr::null_mut()), and avoid using
vm.unwrap_or_none so the function returns NULL when no context is present.

---

Nitpick comments:
In `@crates/capi/src/traceback.rs`:
- Around line 10-13: The function PyTraceBack_Print currently dereferences tb
and file unsafely; add null-pointer checks for the incoming raw pointers (tb and
file) before the unsafe dereferences inside PyTraceBack_Print (the locations
where it does let tb = &*tb and let file = &*file) and return an appropriate
c_int error value (e.g., -1) if either is null (and optionally set a Python
C-API error), otherwise proceed into with_vm as before.
🪄 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: 8fc1a143-8d65-43f6-a6c5-3868e128ca2a

📥 Commits

Reviewing files that changed from the base of the PR and between 883ce9d and 0ecb4a4.

📒 Files selected for processing (4)
  • crates/capi/src/lib.rs
  • crates/capi/src/object.rs
  • crates/capi/src/pyerrors.rs
  • crates/capi/src/traceback.rs

Comment thread crates/capi/src/pyerrors.rs
Copy link
Copy Markdown
Contributor

@ShaharNaveh ShaharNaveh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty:)

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
crates/capi/src/traceback.rs (1)

10-13: 💤 Low value

Consider adding null-pointer guards for defensive safety.

While CPython's C-API generally assumes valid (non-null) pointers and the unsafe marker delegates this responsibility to the caller, dereferencing null pointers would cause undefined behavior. Adding defensive checks would make the function more robust against misuse from C callers.

🛡️ Optional defensive null checks
 pub unsafe extern "C" fn PyTraceBack_Print(tb: *mut PyObject, file: *mut PyObject) -> c_int {
+    if tb.is_null() || file.is_null() {
+        return -1;
+    }
     with_vm(|vm| {
         let tb = unsafe { &*tb };
         let file = unsafe { &*file };
🤖 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/traceback.rs` around lines 10 - 13, Add defensive
null-pointer guards at the start of PyTraceBack_Print: check if the raw pointers
tb or file are null (e.g., tb.is_null() or file.is_null()) before entering the
unsafe dereference or calling with_vm, and if either is null return an error
code (c_int, e.g., -1) so you avoid undefined behavior from dereferencing;
update the function PyTraceBack_Print to perform these checks and early-return
prior to using &*tb or &*file.
🤖 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.

Nitpick comments:
In `@crates/capi/src/traceback.rs`:
- Around line 10-13: Add defensive null-pointer guards at the start of
PyTraceBack_Print: check if the raw pointers tb or file are null (e.g.,
tb.is_null() or file.is_null()) before entering the unsafe dereference or
calling with_vm, and if either is null return an error code (c_int, e.g., -1) so
you avoid undefined behavior from dereferencing; update the function
PyTraceBack_Print to perform these checks and early-return prior to using &*tb
or &*file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: f389499e-0a6e-4d74-a5f1-a8f6d4becfaf

📥 Commits

Reviewing files that changed from the base of the PR and between 0ef4258 and 1b3ad5b.

📒 Files selected for processing (4)
  • crates/capi/src/lib.rs
  • crates/capi/src/object.rs
  • crates/capi/src/pyerrors.rs
  • crates/capi/src/traceback.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/capi/src/object.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/capi/src/lib.rs
  • crates/capi/src/pyerrors.rs

@bschoenmaeckers bschoenmaeckers marked this pull request as draft May 18, 2026 17:36
@bschoenmaeckers bschoenmaeckers marked this pull request as ready for review May 18, 2026 17:53
@youknowone youknowone enabled auto-merge (squash) May 19, 2026 04:33
auto-merge was automatically disabled May 19, 2026 07:44

Head branch was pushed to by a user without write access

@youknowone youknowone enabled auto-merge (squash) May 19, 2026 11:59
auto-merge was automatically disabled May 19, 2026 12:23

Head branch was pushed to by a user without write access

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants