Skip to content

Add tuple support to c-api#7907

Merged
youknowone merged 2 commits into
RustPython:mainfrom
bschoenmaeckers:c-api-tuples
May 19, 2026
Merged

Add tuple support to c-api#7907
youknowone merged 2 commits into
RustPython:mainfrom
bschoenmaeckers:c-api-tuples

Conversation

@bschoenmaeckers
Copy link
Copy Markdown
Contributor

@bschoenmaeckers bschoenmaeckers commented May 18, 2026

Summary by CodeRabbit

  • New Features
    • Introduced comprehensive Python tuple C-API support, enabling type checking, tuple creation, element access, size queries, slice operations, and immutability enforcement.

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: f418d16a-262d-4204-84f9-fda21108babd

📥 Commits

Reviewing files that changed from the base of the PR and between dfe90e5 and 8aebd8a.

📒 Files selected for processing (2)
  • crates/capi/src/lib.rs
  • crates/capi/src/tupleobject.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/capi/src/lib.rs
  • crates/capi/src/tupleobject.rs

📝 Walkthrough

Walkthrough

This PR adds Rust implementations of eight Python tuple C-API entry points (PyTuple_Check, PyTuple_CheckExact, PyTuple_New, PyTuple_FromArray, PyTuple_Size, PyTuple_GetItem, PyTuple_SetItem, PyTuple_GetSlice) and exports them through the tupleobject module, enabling external C code to create, access, and slice tuples while enforcing immutability.

Changes

Tuple C-API Implementation

Layer / File(s) Summary
Module export and type-check infrastructure
crates/capi/src/lib.rs, crates/capi/src/tupleobject.rs
Export the new tupleobject module and define PyTuple_Check/PyTuple_CheckExact type predicates via the C-API type-check macro infrastructure.
Tuple construction from C
crates/capi/src/tupleobject.rs
Implement PyTuple_New with optimized zero-length path and PyTuple_FromArray to construct tuples from raw C pointer arrays with size validation.
Tuple access, mutation, slicing, and validation
crates/capi/src/tupleobject.rs
Implement PyTuple_Size, PyTuple_GetItem, PyTuple_GetSlice for element and slice retrieval, PyTuple_SetItem as an immutability enforcement stub, and include disabled tests covering empty tuple and slice operations.

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • RustPython/RustPython#7871: The new PyTuple_Check/PyTuple_CheckExact exports rely on the define_py_check! macro added in that PR.

Suggested Reviewers

  • youknowone

Poem

🐰 Tuples take shape in the C API land,
With checks and creation carefully planned,
No setters allowed—they're immutable and bright,
Slices and gets make the bindings just right!

🚥 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 pull request title 'Add tuple support to c-api' directly and clearly summarizes the main change: adding C-API tuple functionality to the codebase.
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: 4

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

85-114: 💤 Low value

Permanently disabled test module with no explanation.

#[cfg(false)] ensures these tests never compile or run. If the tests are placeholders or require future work, consider adding a TODO comment explaining when they should be enabled. If they're not applicable (pyo3 tests for a rustpython-vm implementation), consider removing them.

🤖 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/tupleobject.rs` around lines 85 - 114, The test module is
permanently disabled by #[cfg(false)] so the tests (module tests, functions
test_empty_tuple, test_tuple_into_python, test_tuple_get_slice) never compile or
run; either remove the module entirely if these pyo3-based tests are not
applicable to this crate (delete the tests using PyTuple::empty, into_pyobject,
get_slice), or convert it into a real test module by replacing #[cfg(false)]
with #[cfg(test)] and updating the tests to use the crate's supported API (or
add a TODO explaining why they remain disabled) so they can be compiled and run
as intended.
🤖 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/tupleobject.rs`:
- Around line 9-10: The tuple type-check macros use the wrong type constant:
update the calls to define_py_check! for PyTuple_Check and PyTuple_CheckExact to
reference types.tuple_type instead of types.int_type so the macros compare
against the tuple type; locate the two invocations of define_py_check! for
PyTuple_Check and for exact fn PyTuple_CheckExact and replace the type argument
with types.tuple_type.
- Around line 40-47: The function signature for PyTuple_SetItem is wrong: change
the return type from *mut PyObject to c_int (int) and make the function return 0
on success or -1 on error; inside PyTuple_SetItem (currently calling
with_vm::<PyResult, _>(...)) map the Err(vm.new_not_implemented_error(...)) into
an integer return by returning -1 after possibly logging or setting the error
via the VM, and return 0 in the success path (if ever reached). Update any uses
of PyTuple_SetItem to expect an int return value and ensure you import/use c_int
(or i32) for the extern "C" signature and cast/convert Rust results to the
correct integer codes.
- Around line 71-83: PyTuple_GetSlice currently casts low/high isize to usize
directly which wraps negatives; fix by retrieving the tuple length from the
PyTuple (via try_downcast_ref::<PyTuple>), clamp low and high to the valid range
[0, len] (treat negatives as max(0, len + index) or simply clamp low/high
between 0 and len), then convert the clamped usize values and call
do_slice(clamped_low..clamped_high) before creating the new tuple; update
PyTuple_GetSlice to perform this normalization/clamping rather than direct
casting.
- Around line 25-38: The function PyTuple_FromArray casts a potentially negative
isize `size` to usize and calls slice::from_raw_parts, which UB when `size` < 0;
add a guard at the top of PyTuple_FromArray to check `size` is non-negative
before converting and constructing the slice (e.g., if size < 0 return an
error/null pointer or otherwise abort the call), only perform
`slice::from_raw_parts(array, size as usize)` after that validation, and ensure
the early return uses the same return convention expected by
with_vm/vm.new_tuple callers.

---

Nitpick comments:
In `@crates/capi/src/tupleobject.rs`:
- Around line 85-114: The test module is permanently disabled by #[cfg(false)]
so the tests (module tests, functions test_empty_tuple, test_tuple_into_python,
test_tuple_get_slice) never compile or run; either remove the module entirely if
these pyo3-based tests are not applicable to this crate (delete the tests using
PyTuple::empty, into_pyobject, get_slice), or convert it into a real test module
by replacing #[cfg(false)] with #[cfg(test)] and updating the tests to use the
crate's supported API (or add a TODO explaining why they remain disabled) so
they can be compiled and run as intended.
🪄 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: a14a3a8f-27ae-4b8f-b359-8536093c37ef

📥 Commits

Reviewing files that changed from the base of the PR and between 883ce9d and 797843e.

📒 Files selected for processing (3)
  • crates/capi/src/lib.rs
  • crates/capi/src/object.rs
  • crates/capi/src/tupleobject.rs

Comment thread crates/capi/src/tupleobject.rs Outdated
Comment thread crates/capi/src/tupleobject.rs
Comment thread crates/capi/src/tupleobject.rs
Comment thread crates/capi/src/tupleobject.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.

lgtm!

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.

♻️ Duplicate comments (1)
crates/capi/src/tupleobject.rs (1)

10-11: ⚠️ Potential issue | 🔴 Critical

Wrong type used in tuple type-check macros.

Both PyTuple_Check and PyTuple_CheckExact still reference types.int_type instead of types.tuple_type. This causes tuple type checks to fail on actual tuples while succeeding on integers.

🤖 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/tupleobject.rs` around lines 10 - 11, The tuple type-check
macros use the wrong target type: update the two macro invocations using
define_py_check!(fn PyTuple_Check, types.int_type) and define_py_check!(exact fn
PyTuple_CheckExact, types.int_type) to reference types.tuple_type instead of
types.int_type so PyTuple_Check and PyTuple_CheckExact perform checks against
the tuple type; keep the same macro form (define_py_check!) and only change the
second argument to types.tuple_type for both PyTuple_Check and
PyTuple_CheckExact.
🧹 Nitpick comments (1)
crates/capi/src/tupleobject.rs (1)

93-122: 💤 Low value

Consider alternative approach for disabled tests.

Using #[cfg(false)] permanently disables this code from compilation. If these tests are intended for future use, consider using #[cfg(feature = "pyo3-tests")] with an optional feature flag, or move them to an integration test file that depends on pyo3. This would allow running them when the appropriate dependencies are available.

🤖 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/tupleobject.rs` around lines 93 - 122, The test module is
permanently disabled by #[cfg(false)]; replace that attribute with a conditional
feature flag like #[cfg(feature = "pyo3-tests")] so the tests (module tests and
its functions test_empty_tuple, test_tuple_into_python, test_tuple_get_slice
which call PyTuple::empty, into_pyobject, and get_slice) can be compiled when
the optional feature is enabled, or alternatively move the tests into an
integration test under tests/ (removing the cfg) and add pyo3 as a
dev-dependency so they run only in a test context.
🤖 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.

Duplicate comments:
In `@crates/capi/src/tupleobject.rs`:
- Around line 10-11: The tuple type-check macros use the wrong target type:
update the two macro invocations using define_py_check!(fn PyTuple_Check,
types.int_type) and define_py_check!(exact fn PyTuple_CheckExact,
types.int_type) to reference types.tuple_type instead of types.int_type so
PyTuple_Check and PyTuple_CheckExact perform checks against the tuple type; keep
the same macro form (define_py_check!) and only change the second argument to
types.tuple_type for both PyTuple_Check and PyTuple_CheckExact.

---

Nitpick comments:
In `@crates/capi/src/tupleobject.rs`:
- Around line 93-122: The test module is permanently disabled by #[cfg(false)];
replace that attribute with a conditional feature flag like #[cfg(feature =
"pyo3-tests")] so the tests (module tests and its functions test_empty_tuple,
test_tuple_into_python, test_tuple_get_slice which call PyTuple::empty,
into_pyobject, and get_slice) can be compiled when the optional feature is
enabled, or alternatively move the tests into an integration test under tests/
(removing the cfg) and add pyo3 as a dev-dependency so they run only in a test
context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 368ee864-ac46-408b-935e-6374f1c49d4c

📥 Commits

Reviewing files that changed from the base of the PR and between 797843e and 6b694fd.

📒 Files selected for processing (1)
  • crates/capi/src/tupleobject.rs

@youknowone youknowone merged commit 276a0e6 into RustPython:main May 19, 2026
26 checks passed
@bschoenmaeckers bschoenmaeckers deleted the c-api-tuples branch May 20, 2026 12:02
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