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

DM-15187: Modernize sphgeom pickle support for pybind11 2. #17

Merged
merged 2 commits into from Jul 24, 2018

Conversation

r-owen
Copy link
Contributor

@r-owen r-owen commented Jul 23, 2018

No description provided.

@r-owen r-owen requested a review from pschella July 23, 2018 20:42
});
cls.def(py::pickle(
[](const Box &self) { return python::encode(self); },
[](py::bytes bytes) { return decode(bytes).release(); }));

Choose a reason for hiding this comment

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

Are you sure the explicit release is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question, but I was hoping you could tell me! I copied the code from the existing wrappers for decode (e.g. in box.cc, ellipse.cc, etc.). However, I did try building without .release() in the pickle wrapper (but not in the decode wrapper) and I didn't see any difference -- the unit tests passed. I figured it was safer to go with what was there, but it might be code that was never needed, or was only needed for older versions of pybind11. What do you 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.

http://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html this implies that the release is not needed (and perhaps not wanted).

Copy link
Contributor Author

@r-owen r-owen Jul 24, 2018

Choose a reason for hiding this comment

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

Based on more tests I see the following:

  • If I remove .release() from clone or decode in region.cc I get segfaults
  • If I remove .release() from decode in box.cc I also get segfaults
  • If I remove .release() from the pickle wrapper in box.cc I do not get segfaults

Do you know what's going on? The py::class_ templates do list std::shared_ptr<X> for each type X, as usual for LSST. Does this cause trouble for functions that return a unique pointer to X? Why does the pickle support seem to work without release() when the identical decode does not?

Barring an explanation and a commensurate desire to change something, I propose to leave the .release() in everywhere.

Choose a reason for hiding this comment

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

I agree with the proposed solution. Will have to look into this later. Perhaps file a new mini ticket? The unique_ptr -> shared_ptr shouldn't matter.

cls.def(py::pickle([](UnitVector3d const &self) { return py::make_tuple(self.x(), self.y(), self.z()); },
[](py::tuple t) {
if (t.size() != 3) {
throw std::runtime_error("Invalid state!");

Choose a reason for hiding this comment

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

You may want to be a bit more explicit.

throw std::runtime_error("Invalid state!");
}
return new UnitVector3d(UnitVector3d::fromNormalized(
t[0].cast<double>(), t[1].cast<double>(), t[2].cast<double>()));

Choose a reason for hiding this comment

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

I know this was already there, but why a heap one?

Copy link
Contributor Author

@r-owen r-owen Jul 24, 2018

Choose a reason for hiding this comment

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

I'm not sure what you are asking. Are you asking why this code returns a pointer instead of a vector? If so, my guess is because UnitVector3d has no move constructor -- though I don't know if the compiler would still manage to move the data in this situation. In any case...pybind11 pickle docs show returning the new object by bare pointer, so it is a reasonable option. If you think something else would be better let me know.

Use pybind11::pickle instead of defining `__getstate__`
and `__setstate__` directly, as recommended for pybind11 2.2.
This eliminates compiler warnings.
Copy link

@pschella pschella left a comment

Choose a reason for hiding this comment

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

See previous comments.

});
cls.def(py::pickle(
[](const Box &self) { return python::encode(self); },
[](py::bytes bytes) { return decode(bytes).release(); }));

Choose a reason for hiding this comment

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

I agree with the proposed solution. Will have to look into this later. Perhaps file a new mini ticket? The unique_ptr -> shared_ptr shouldn't matter.

@r-owen r-owen merged commit 32814cc into master Jul 24, 2018
@ktlim ktlim deleted the tickets/DM-15187 branch August 25, 2018 05:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants