Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added From<Bound<'py, T>> impl for PyClassInitializer<T>. #4214

Merged
merged 5 commits into from
May 28, 2024

Conversation

JRRudy1
Copy link
Contributor

@JRRudy1 JRRudy1 commented May 28, 2024

This is a tiny change that allows Bound<T> to be returned from a pyclass's #[new] method, as is already supported for Py<T>.

This flexibility would be convenient in certain cases; for example, it is often desirable to have a constructor for use on the Rust-side that returns the type as a Python object (Py<T> or Bound<T>) instead of T directly (e.g. when you want to be able to downcast into T::BaseClass). And as long your desired arguments are the same as for your #[new] method, you can just reuse the same constructor for use from both Python and Rust. However, you are currently limited to getting a Py<T> from this, which usually has to be followed by .into_bound(py) if you want to do anything useful with it. But if you could have the #[new] method return Bound<T> instead, as implemented by this PR, then it would be more ergonomic to call from Rust (while making no difference on the Python side). I also think it just makes sense intuitively, since Bound<T> is essentially just Py<T> with superpowers.

In my opinion this change is too trivial to warrant adding tests, but let me know if you disagree and I can add some.

@alex
Copy link
Contributor

alex commented May 28, 2024

Please add a test -- they're not just to ensure that this implementation is correct (and I agree, it looks trivial), they're also to ensure that as we refactor and change our APIs in the future, we don't break this.

@JRRudy1
Copy link
Contributor Author

JRRudy1 commented May 28, 2024

Please add a test -- they're not just to ensure that this implementation is correct (and I agree, it looks trivial), they're also to ensure that as we refactor and change our APIs in the future, we don't break this.

No problem, done!

@JRRudy1
Copy link
Contributor Author

JRRudy1 commented May 28, 2024

Actually something failed, sorry I'll fix it.

#[test]
fn test_new_returns_bound() {
Python::with_gil(|py| {
let obj = NewReturnsBound::new(py).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

This just calls new, it doesn't actually invoke the mechanism you added.

Take a look at test_new_existing in this file for how you can test it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm that's weird, it definitely hits the new From impl indirectly in the call sequence (the macro-generated __pymethod___new____ calls IntoPyCallbackOutput::convert on the Bound<T> which calls <Bound<T> as Into<_>>::into and then From::from), but I guess its not direct enough for the coverage runner to detect. Thanks for the tip, I am very new to CI :)

Copy link
Contributor Author

@JRRudy1 JRRudy1 May 28, 2024

Choose a reason for hiding this comment

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

Oh wait, the Rust-side call obviously doesn't actually invoke the __pymethod___new____ stuff, duh! I'll fix it now

@alex alex added this pull request to the merge queue May 28, 2024
@alex
Copy link
Contributor

alex commented May 28, 2024

Thanks

Merged via the queue into PyO3:main with commit 934c663 May 28, 2024
43 checks passed
@JRRudy1 JRRudy1 deleted the pyclassinit-from-bound branch May 28, 2024 02:35
@JRRudy1
Copy link
Contributor Author

JRRudy1 commented May 28, 2024

No problem, thanks for the merge!

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.

2 participants