Skip to content

Add pyframe functions to c-api#8215

Merged
youknowone merged 2 commits into
RustPython:mainfrom
bschoenmaeckers:c-api-frame
Jul 6, 2026
Merged

Add pyframe functions to c-api#8215
youknowone merged 2 commits into
RustPython:mainfrom
bschoenmaeckers:c-api-frame

Conversation

@bschoenmaeckers

@bschoenmaeckers bschoenmaeckers commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added a new public API module for accessing runtime frame details from RustPython.
    • Added external entrypoints to retrieve a frame’s code object and its computed source line number.
  • Chores
    • Updated spell-check dictionary with the new term.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new public pyframe FFI module to the capi crate with PyFrame_GetCode and PyFrame_GetLineNumber, and updates the spelling dictionary for the new module name.

Changes

PyFrame FFI Module

Layer / File(s) Summary
Module registration and frame FFI functions
crates/capi/src/lib.rs, crates/capi/src/pyframe.rs, .cspell.dict/cpython.txt
Declares the new public pyframe module, implements PyFrame_GetCode and PyFrame_GetLineNumber for RustPython VM frames, and adds the pyframe dictionary entry.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant PyFrameAPI as PyFrame FFI
  participant VM as with_vm
  participant Frame

  Caller->>PyFrameAPI: PyFrame_GetCode(frame)
  PyFrameAPI->>VM: with_vm(downcast to Frame)
  VM->>Frame: try_downcast_ref
  Frame-->>VM: code object
  VM-->>PyFrameAPI: *mut PyObject
  PyFrameAPI-->>Caller: return code pointer

  Caller->>PyFrameAPI: PyFrame_GetLineNumber(frame)
  PyFrameAPI->>VM: with_vm(downcast to Frame)
  VM->>Frame: try_downcast_ref
  Frame-->>VM: line number
  VM-->>PyFrameAPI: c_int
  PyFrameAPI-->>Caller: return line number
Loading

Suggested reviewers: ShaharNaveh, youknowone

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Title check ✅ Passed The title accurately summarizes the main change: adding pyframe functions to the C API.
✨ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
crates/capi/src/pyframe.rs (2)

6-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse Frame::f_code() instead of touching the field directly.

crates/vm/src/builtins/frame.rs already exposes a public accessor for this: The Frame f_code accessor returns self.code.clone(). Calling frame.f_code() here avoids depending on the code field's visibility/shape directly from another crate and keeps a single source of truth if the accessor logic ever changes.

♻️ Proposed refactor
     with_vm(|vm| {
         let frame = unsafe { &*frame }.try_downcast_ref::<Frame>(vm)?;
-        Ok(frame.code.clone())
+        Ok(frame.f_code())
     })
🤖 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/pyframe.rs` around lines 6 - 11, Refactor PyFrame_GetCode to
use the public Frame::f_code() accessor instead of cloning frame.code directly.
In the PyFrame_GetCode function, keep the existing try_downcast_ref::<Frame>(vm)
lookup, then call frame.f_code() to obtain the code object so this crate depends
on the accessor rather than the Frame field layout. This keeps the
implementation aligned with the Frame API in builtins::frame::Frame and
preserves a single source of truth for code retrieval.

14-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated line-number logic — reuse Frame::f_lineno().

This re-implements the exact branching already defined publicly on Frame: f_lineno selects first_line_number when lasti()==0, otherwise uses current_location().line.get(). The lasti()==0 guard exists specifically to avoid an underflow in current_location()'s locations[self.lasti()-1] indexing — duplicating this here risks silent divergence if that VM-side logic is ever changed (e.g. bug fix, edge-case handling) without updating this copy.

♻️ Proposed refactor
     with_vm(|vm| {
         let frame = unsafe { &*frame }.try_downcast_ref::<Frame>(vm)?;
-        let lineno = if frame.lasti() == 0 {
-            frame.code.first_line_number.map_or(1, |n| n.get())
-        } else {
-            frame.current_location().line.get()
-        };
-        Ok(lineno as core::ffi::c_int)
+        Ok(frame.f_lineno() as core::ffi::c_int)
     })
🤖 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/pyframe.rs` around lines 14 - 24, Replace the duplicated
line-number branching in PyFrame_GetLineNumber with the existing
Frame::f_lineno() logic instead of re-implementing the
lasti()/first_line_number/current_location() check here. Keep the unsafe frame
cast and VM lookup in PyFrame_GetLineNumber, but delegate the actual line-number
retrieval to Frame::f_lineno() so this C API entry point stays consistent with
the Frame method and won’t drift if the VM-side behavior changes.
🤖 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/pyframe.rs`:
- Around line 6-11: Refactor PyFrame_GetCode to use the public Frame::f_code()
accessor instead of cloning frame.code directly. In the PyFrame_GetCode
function, keep the existing try_downcast_ref::<Frame>(vm) lookup, then call
frame.f_code() to obtain the code object so this crate depends on the accessor
rather than the Frame field layout. This keeps the implementation aligned with
the Frame API in builtins::frame::Frame and preserves a single source of truth
for code retrieval.
- Around line 14-24: Replace the duplicated line-number branching in
PyFrame_GetLineNumber with the existing Frame::f_lineno() logic instead of
re-implementing the lasti()/first_line_number/current_location() check here.
Keep the unsafe frame cast and VM lookup in PyFrame_GetLineNumber, but delegate
the actual line-number retrieval to Frame::f_lineno() so this C API entry point
stays consistent with the Frame method and won’t drift if the VM-side behavior
changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: e5ba2ad3-9271-4bff-aade-3ca1b607d7bb

📥 Commits

Reviewing files that changed from the base of the PR and between 3f9d80b and 22d84b6.

📒 Files selected for processing (2)
  • crates/capi/src/lib.rs
  • crates/capi/src/pyframe.rs

@ShaharNaveh ShaharNaveh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ty:)

@youknowone youknowone merged commit 28829a7 into RustPython:main Jul 6, 2026
25 of 26 checks passed
@bschoenmaeckers bschoenmaeckers deleted the c-api-frame branch July 7, 2026 08:53
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