Skip to content

pyarrow: Wrap capsule extraction errors into an explicit error - #9660

Merged
alamb merged 8 commits into
apache:mainfrom
Tpt:tpt/pyarrow-capsule
Jun 22, 2026
Merged

pyarrow: Wrap capsule extraction errors into an explicit error#9660
alamb merged 8 commits into
apache:mainfrom
Tpt:tpt/pyarrow-capsule

Conversation

@Tpt

@Tpt Tpt commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Remove validate_pycapsule: pointer_checked already raises an exception if the capsule type is wrong, and we wrap it into a nicer error

Also relies on a trait to associate types with their capsules names

Because we wrap the exception (equivalent of raise X from Y), the original exception is still there

Follow up of #9639 #9594

@Tpt
Tpt force-pushed the tpt/pyarrow-capsule branch 2 times, most recently from aa910ff to 61391e3 Compare April 4, 2026 17:21
@Tpt

Tpt commented Apr 16, 2026

Copy link
Copy Markdown
Contributor Author

@alamb Thank you for the rebase. This MR is blocked by a segfault. I have not understood why yet and put this MR on hold to go back to it with a fresh mind. I will try to debug that in the next few days. Sorry for having it been stalled for so long.

Update: got it working, there was a use-after-free error.

@Tpt
Tpt force-pushed the tpt/pyarrow-capsule branch from f0b61da to 7ecba54 Compare April 16, 2026 19:28
@Tpt
Tpt marked this pull request as ready for review April 16, 2026 19:29
@Tpt
Tpt force-pushed the tpt/pyarrow-capsule branch from b1880b6 to 240fd32 Compare April 17, 2026 09:21
Tpt added 3 commits June 16, 2026 17:01
Remove validate_pycapsule: pointer_checked already raises an exception if the capsule type is wrong, and we wrap it into a nicer error
@Tpt
Tpt force-pushed the tpt/pyarrow-capsule branch from 240fd32 to 6c51b43 Compare June 16, 2026 15:03
@Tpt

Tpt commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@timsaucer I would love to get some review on this MR. It cleans up both code and error messages

@timsaucer timsaucer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's a nice cleanup. Adding a trait that just contains a constant seems like it adds complexity with minimal value. Otherwise I'm good with the changes.

Comment thread arrow-pyarrow/src/lib.rs Outdated
Comment on lines +582 to +596
trait PyCapsuleType {
const NAME: &CStr;
}

impl PyCapsuleType for FFI_ArrowSchema {
const NAME: &CStr = c"arrow_schema";
}

impl PyCapsuleType for FFI_ArrowArray {
const NAME: &CStr = c"arrow_array";
}

impl PyCapsuleType for FFI_ArrowArrayStream {
const NAME: &CStr = c"arrow_array_stream";
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems like overkill. Why not just keep these as constants like we had before and pass them as needed?

@Tpt Tpt Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My motivation for the trait is to have a single place to associate a type with its capsule name (the impl block) and to avoid the possible mistake of using a wrong capsule name at an extract_capsule call site. This also allows to keep the capsule name concern outside of the main code logic.

No other motivation outside of this small "fool-proofing". Glad to remove it if you prefer.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not a committer on this repo, so I'd leave it to them for final say. My recommendation would be to keep it simpler.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Other than that, it's a very nice cleanup and I may steal this idea over in datafusion-python.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nice! I have also ideas for follow ups (use string interning...). Very happy to help also on the datafusion-python side.

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.

I agree with @timsaucer -- keeping the code simpler would be my preference but this looks ok too

@Tpt Tpt Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Trait removed: 2ab7223 (fun fact, the number of LOC has not changed)

@alamb alamb 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.

Looks like a nice improvement to me -- thanks @Tpt

I defer to @timsaucer (or @kylebarron ) for the specifics

Comment thread arrow-pyarrow/src/lib.rs Outdated
Comment on lines +582 to +596
trait PyCapsuleType {
const NAME: &CStr;
}

impl PyCapsuleType for FFI_ArrowSchema {
const NAME: &CStr = c"arrow_schema";
}

impl PyCapsuleType for FFI_ArrowArray {
const NAME: &CStr = c"arrow_array";
}

impl PyCapsuleType for FFI_ArrowArrayStream {
const NAME: &CStr = c"arrow_array_stream";
}

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.

I agree with @timsaucer -- keeping the code simpler would be my preference but this looks ok too

assert!(err.is_instance_of::<PyTypeError>(py));
assert_eq!(
err.to_string(),
"TypeError: Expected __arrow_c_array__ to return a tuple of (schema, array) capsules."

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure if it's necessary here because these are integration tests, not user-facing, but I think the old language was more explicit

@Tpt Tpt Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Indeed. I have reverted the error message change: 1f72b24

@kylebarron

Copy link
Copy Markdown
Member

Sorry I can't tell what the difference is with this PR. What's the user-facing difference between before and after?

@Tpt
Tpt force-pushed the tpt/pyarrow-capsule branch from c95726c to 56218cd Compare June 17, 2026 19:07
@Tpt

Tpt commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Sorry I can't tell what the difference is with this PR. What's the user-facing difference between before and after?

Sorry, I should have made it more explicit. 56218cd add a test to highlight the change.

Before the change, when calling a method that must return a capsule but does not actually return one:

TypeError: 'int' object is not an instance of 'PyCapsule'

After:

TypeError: Expected arrow_c_schema to return a capsule.

@alamb
alamb merged commit 45f008a into apache:main Jun 22, 2026
14 checks passed
@alamb

alamb commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Thank you @Tpt @timsaucer and @kylebarron

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.

4 participants