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

migrate PyDictMethods trait bounds #4493

Merged
merged 5 commits into from
Oct 1, 2024
Merged

migrate PyDictMethods trait bounds #4493

merged 5 commits into from
Oct 1, 2024

Conversation

Icxolu
Copy link
Contributor

@Icxolu Icxolu commented Aug 25, 2024

This migrates PyDictMethods to IntoPyObject and cleans up the map impls. I was not super sure how we want to deal with IntoPyDict, so I added a proposal as a second commit, but we can also drop that for now, if we need more discussion for that. In case we want to leave it like this, I will add changelog and migration entries.

@Icxolu Icxolu added the CI-skip-changelog Skip checking changelog entry label Aug 25, 2024
Copy link
Contributor

@LilyFoote LilyFoote left a comment

Choose a reason for hiding this comment

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

The first commit looks good to me.

@Icxolu Icxolu mentioned this pull request Sep 13, 2024
3 tasks
Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Thanks, agreed on the first commit looking great! Some suggestions on the second commit...

Comment on lines 560 to 563
pub trait IntoPyDict<'py>: Sized {
/// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed
/// depends on implementation.
fn into_py_dict(self, py: Python<'_>) -> Bound<'_, PyDict>;
fn into_py_dict(self, py: Python<'py>) -> Bound<'_, PyDict>;
Copy link
Member

Choose a reason for hiding this comment

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

I think we can take the opportunity here to make the return type fallible? AFAIK one of the most likely panics on current conversion traits is unhashable keys.

(This method is new for 0.23 replacing the removed GIL Ref form)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes sense, I will adapt that 👍

Comment on lines 589 to 595
/// Represents a tuple which can be used as a PyDict item.
pub trait PyDictItem {
type K: ToPyObject;
type V: ToPyObject;
fn key(&self) -> &Self::K;
fn value(&self) -> &Self::V;
pub trait PyDictItem<'py> {
type K: IntoPyObject<'py>;
type V: IntoPyObject<'py>;
fn unpack(self) -> (Self::K, Self::V);
}
Copy link
Member

Choose a reason for hiding this comment

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

It's kind of breaking, but I can't really see a better way forward. Maybe we just mention this in the migration guide? Most users are not implementing / using this trait, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I think PyDictItem is completely internal to PyO3 and is invisible from the outside (it's only mentioned inside dict.rs which is a pub(crate) module). So maybe we just remove pub here to make that clear? Also we should update the example that's already in the migration guide in that regard. I will fix it up together with the fallibility mention.

Copy link
Member

Choose a reason for hiding this comment

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

Ah perfect, even better! We might need to have pub for the trait implementation, not sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed it and nothing complained, so it guess it's fine 😁

@@ -557,76 +557,73 @@ pub(crate) use borrowed_iter::BorrowedDictIter;

/// Conversion trait that allows a sequence of tuples to be converted into `PyDict`
/// Primary use case for this trait is `call` and `call_method` methods as keywords argument.
pub trait IntoPyDict: Sized {
pub trait IntoPyDict<'py>: Sized {
Copy link
Member

Choose a reason for hiding this comment

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

I guess the alternative is keep the existing form around for a while and add a new trait IntoPyDictObject or similar which we can eventually rename back to just this. But I'm unsure how much value there really is in that, for this small corner of the API.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have the feeling that this is mostly used to get access to the constructors we provide and is probably not often implemented on custom types. So I think it would likely cause more churn doing the renaming business.

Copy link
Member

Choose a reason for hiding this comment

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

Agreed, let's keep with this current pathway 👍

@Icxolu Icxolu removed the CI-skip-changelog Skip checking changelog entry label Oct 1, 2024
Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Looks great to me, thanks! Basically just some closing thoughts / observations remaining. Please feel free to merge 👍

src/conversions/indexmap.rs Outdated Show resolved Hide resolved
@@ -557,76 +557,73 @@ pub(crate) use borrowed_iter::BorrowedDictIter;

/// Conversion trait that allows a sequence of tuples to be converted into `PyDict`
/// Primary use case for this trait is `call` and `call_method` methods as keywords argument.
pub trait IntoPyDict: Sized {
pub trait IntoPyDict<'py>: Sized {
Copy link
Member

Choose a reason for hiding this comment

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

Agreed, let's keep with this current pathway 👍

Comment on lines 582 to 585
for item in self {
dict.set_item(item.key(), item.value())
.expect("Failed to set_item on dict");
let (key, value) = item.unpack();
dict.set_item(key, value)?;
}
Copy link
Member

Choose a reason for hiding this comment

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

(Probably one for a future PR) I guess after I read https://medium.com/@veedrac/rust-is-slow-and-i-am-the-cure-32facc0fdcb we should eventually consider try_for_each or similar iterator algorithms for these loops. Potentially extra relevant after #4439.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting read, thanks for linking. Might be interesting to do some benchmarks whether we can actually measure any difference. Sounds good for a future PR for me too.

Comment on lines 589 to 595
/// Represents a tuple which can be used as a PyDict item.
pub trait PyDictItem {
type K: ToPyObject;
type V: ToPyObject;
fn key(&self) -> &Self::K;
fn value(&self) -> &Self::V;
pub trait PyDictItem<'py> {
type K: IntoPyObject<'py>;
type V: IntoPyObject<'py>;
fn unpack(self) -> (Self::K, Self::V);
}
Copy link
Member

Choose a reason for hiding this comment

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

Ah perfect, even better! We might need to have pub for the trait implementation, not sure.

Co-authored-by: David Hewitt <[email protected]>
@Icxolu Icxolu enabled auto-merge October 1, 2024 20:20
@Icxolu Icxolu added this pull request to the merge queue Oct 1, 2024
Merged via the queue into PyO3:main with commit faed5e2 Oct 1, 2024
40 of 42 checks passed
@Icxolu Icxolu deleted the migrate-pydict branch October 1, 2024 23:45
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