Skip to content

Python bindings with PyO3 #51

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

Merged
merged 135 commits into from
Sep 9, 2021
Merged

Python bindings with PyO3 #51

merged 135 commits into from
Sep 9, 2021

Conversation

alecandido
Copy link
Member

Hi @cschwan, I was reading about PyO3, and after a while I started thinking that it may be not so hard to provide bindings for pineappl using it.

I don't know how much you care, but I decided to make a try, just in my spare time. The goal it's to port a minimal subset of things, just a proof of concept, to expand after to the full one.

It should not take so much, but of course it's not my main business, so it will take its time. Do you mind if I try?

I also thought it was a good way to familiarize a little more with pineappl, since soon it will be useful (both because of yadism, but also because I am going to work on pineko too, and I know you are the expert on pineappl, but it won't hurt to know something more).

If you agree maybe you can suggest me which one could be "a minimal set".

@alecandido alecandido changed the base branch from master to dis December 13, 2020 19:36
@cschwan
Copy link
Contributor

cschwan commented Dec 14, 2020

Hi @alecandido , I don't mind at all, and in fact I think that would be very useful. Go ahead, and let me know if you need to know anything.

For a minimal set of structs and methods, just have a look at #50 , in particular the file https://github.com/N3PDF/pineappl/pull/50/files#diff-4a3c785edeb3672939e989f1aedce3a888747e39fabed535fba4a7909f13f7b2. This file more or less contains everything important from the user side.

Don't forget to change the author of pineappl_py to yourself.

@alecandido
Copy link
Member Author

First, small, trade off due to python + rust interaction:

  • maturin, the zero-configuration tool for building and deploying pyo3 packages, it's enforcing a specific layout, and it is perfectly fine
  • unfortunately, the name of the PyPI package will be the same of the rust package:
    • in both the case of a pure rust package and a mixed python/rust one you are free to choose (the same) unrestricted name for the import package (i.e. the name you use when you do in python import my_package)
    • but there is another name involved: the one you use to do pip install my-package, and it's the distribution package

And now the problem: while the current python package it's named pineappl (and it makes sense), now we can't choose that name any longer, using maturin, because, since it's extracted from Cargo.toml package.name, picking pineappl would conflict with the other one (the original) in the workspace.

Maybe we can overcome this little pain by using setuptools_rust, but it's far more verbose and requires many more files (i.e. at least a couple), rather than the simple standard/enforced layout of maturin.

Is it worth?
(we can call pineappl_py the distr package and still do import pineappl`, i.e. what I'm currently doing)

@cschwan
Copy link
Contributor

cschwan commented Dec 22, 2020

It's probably best to rename it, since keeping the name of the other python package suggest they're compatible, which they probably won't.

@alecandido
Copy link
Member Author

You're right, we can think a little on the name (pineappl_py, pineappl-py, pyneappl, ...), but it's just the installation one for distribution package, so you will simply find pineappl_py when you search on PyPI, slightly uglier but it has the further advantage of being explicit: it's not shipping the rust lib only (possible for PyPI but useless) but also the proper bindings, even if it's of course expected from a PyPI package...

And it will keep the complexity low, without any extra than bindings themselves.

* 'pyo3' of github.com:N3PDF/pineappl:
  Add a small note on maturin workflow
  Fix final layout (hopefully)
@cschwan
Copy link
Contributor

cschwan commented Dec 23, 2020

Do we actually need a separate crate for the python bindings? It might be beneficial to put everything into the main crate, preferably only when the python feature is activated. In this way there's less code duplication and adding a method is easy (?!).

@alecandido
Copy link
Member Author

alecandido commented Dec 23, 2020

You're right, doing it in the main crate would be easier, but when I decided to split I made two considerations:

  1. maybe python it's not so special, so why is the C one split and python should fit in the main one? And in this way the python would be rather more coupled, because the development of python wrappers it's somehow interleaved in the library itself
  2. I didn't want to mess up with the library myself, because in this way I was completely sure that I wasn't ruining anything at all

On the other hand there are some pros:

  • there are examples of other projects doing the same
  • maturin itself it's supporting this layout
  • I probably need some python code for making proper classes (because of limitations of pyo3 and the struct-class mismatch) and for this I had to make a pineappl package (it would be pineappl/pineappl/pineappl inside the main crate)

Nevertheless being outside the main crate I need to wrap all the structs and functions to annotate them, and it's a pain in the neck, so it would be much better to use the main crate just for this reason.

What do you think?

@cschwan
Copy link
Contributor

cschwan commented Dec 23, 2020

If it isn't master you can do whatever you like. I'm more concerned that whenever I add new Rust code in the future, I'll have to update lots of code in other places. This already happens for the C API, which definitely doesn't support all methods the Rust interface has. I was already thinking about merging the pineappl_capi into pineappl. But for the time being we should focus on adding the functionality.

@alecandido
Copy link
Member Author

Fine. Let's say that since I started this way I'll try to complete just the proof of concept, with the goal of running import-yadism-yaml.py with the new wrapper.

As soon as I get there we can merge in dis and than decide the best layout. Just not to get lost in changes.

@cschwan
Copy link
Contributor

cschwan commented Dec 23, 2020

Agreed!

@felixhekhorn
Copy link
Contributor

@felixhekhorn
Copy link
Contributor

do we need PyBinRemapper?

it is still used here: https://github.com/N3PDF/yadism/blob/be995caf3a7f76dafd06336ba83fc570bc31f0a3/src/yadism/output.py#L236
so I guess the answer is yes ... or is there some other way?

@felixhekhorn
Copy link
Contributor

add tests
add more documentation

actually, where? Rust@pineappl, Rust@pineappl_py, Python@pineappl_py ?

@felixhekhorn
Copy link
Contributor

check README

I made a proposal in e8e1809 - please take a look

@cschwan
Copy link
Contributor

cschwan commented Sep 7, 2021

add tests
add more documentation

actually, where? Rust@pineappl, Rust@pineappl_py, Python@pineappl_py ?

What I'd like to see is tests of the Python interface, so tests written in Python!

@cschwan cschwan merged commit 3d8955b into master Sep 9, 2021
@cschwan cschwan deleted the pyo3 branch September 9, 2021 14:58
@cschwan cschwan mentioned this pull request Sep 9, 2021
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