Closed wshanks closed 4 months ago
Woah, haha. Do you know what version of PyO3 is being used in the lockfile for that build?
I would not imagine that any component of this would actually work with PyPy, but who knows - I don't really know the details of how their hook points to the CPython C API work. Certainly we've never attempted to build PyPy wheels on our side.
Ohhhh wait sorry, I just clicked through. Yeah, I guess if modules don't have filename attributes on PyPy, then that just isn't going to work. Do you know if they have __file__
attributes in Python space / is it just the C-API side that's missing?
Do you know what version of PyO3 is being used in the lockfile for that build?
I force-pushed so the failed build is hard to find. It is here. The pyo3 version was v0.20.2.
Certainly we've never attempted to build PyPy wheels on our side.
Yes, I haven't used them either, so I don't know how high a priority this is, but it was at least building in the terra feedstock here.
Do you know if they have file attributes in Python space / is it just the C-API side that's missing?
$ pypy -c "import os; print(os.__file__)"
/home/wshanks/.conda/envs/pypy/lib/pypy3.9/os.py
It seems to work for Python files. It's kind of strange. There's not much information in that PyO3 commit that disabled the function for PyPy.
Flicking through, it looks like PyO3 uses the semi-private _PyModule_GetFilename
function to power that method, which PyPy presumably doesn't include. In theory, that line is super minor and nowhere even close to performance critical, so I could switch it to a Python-space access to __file__
, which I imagine would work in PyPy. As we use Rust more and more, though, it's ever more likely that we'll break the PyPy build by using some other C API stuff that's not compatible with PyPy, and we won't catch that in CI, because we don't really have the resources to test PyPy.
So, while the particular fix here would be super easy, I guess the question is: do we want to keep playing whack-a-mole with PyPy issues post release, when the conda-feedstock tries the build and tells us about them, or do we just want to entirely write off PyPy support now? We've never really considered it before, and I didn't actually realise we were ever trying to build PyPy wheels.
We can also punt the question by fixing this particular issue and seeing if further issues actually turn up.
Yeah this is the first time someone has reported this. FWIW, I saw this coming years ago when we first started using rustworkx as a dependency (and that we don't build pypy wheels for rustworkx) and it's why I put:
Additionally, Qiskit only supports CPython. Running with other Python interpreters is not supported.
in the platform support documentation:
https://docs.quantum.ibm.com/start/install#operating-system-support
That being said how important is this for the conda build system? I would expect a lot of our dependencies don't support pypy either.
EDIT: Oops missed you called out CPython is the only supported platform in the docs already. I will say if we can make it work for you on pypy with very little effort we should do that. It's more this will likely happen again in the future as we use more Rust code in Qiskit and we don't test or build for pypy anywhere.
it's why I put:
Additionally, Qiskit only supports CPython. Running with other Python interpreters is not supported.
in the platform support documentation:
Ack, I linked right to that part of the documentation above but glossed over that statement since the section was name "operating system support". Perhaps one action item would be to update that section to be "Operating system and Python implementation support" and then at "other Python interpreters" add "such as PyPy" so it comes up more readily in a search for "qiskit pypy". I am not sure if there are any other likely cases besides PyPy that someone might search for? Maybe wasm/wasi which have been getting more attention recently.
That being said how important is this for the conda build system? I would expect a lot of our dependencies don't support pypy either.
I don't think it has any particular importance. The other maintainer of qiskit-terra had enabled PyPy builds, probably because the automation opens a PR to enable them by default and the build ran without errors. I could just drop PyPy builds and see if anyone asks for them. I opened the issue because they had been building and stopped with 1.0 and I wasn't sure if it was "don't support at all" or a "best effort to keep working" kind of issue.
The automation also tried to enable PyPy for Aer but ran into a build error. I didn't understand the build error (but might have been due to missing support from pybind11), so I left the PyPy PR unmerged with a comment that it could be looked at more if anyone wanted it. That was a year ago and I haven't heard anything so far.
With conda install qiskit pypy stestr ddt
(so no optionals, mainly because I forgot about them before starting the tests), this was the result for stestr run
:
======
Totals
======
Ran: 21975 tests in 2358.0034 sec.
- Passed: 21476
- Skipped: 484
- Expected Fail: 5
- Unexpected Success: 0
- Failed: 10
Sum of execute time for each test: 16864.2666 sec.
Here is the full failure set. Some of the failures might reflect some hidden assumptions that could be fixed for CPython. It looks like TestOperator.test_drawings
is missing a HAS_IPYTHON
and maybe some of the tests assume ordering where there isn't guaranteed ordering.
Regarding playing whack-a-mole, I asked the PyPy maintainers about C-API coverage. PyPy should have pretty good coverage of the limited stable C-API, which I think Qiskit is opting into by using the abi3
option of PyO3. One of the PyPy maintainers told me that API methods that return char *
are hard for PyPy to deal with. In this case, PyModule_GetFilename
is actually deprecated in favor of PyModule_GetFilenameObject. That was also not implemented in PyPy but the maintainer added an implementation for it when answering my question. Maybe Qiskit should switch to using PyModule_GetFilenameObject
any way?
We don't really make a choice between PyModule_GetFilename
and PyModule_GetFilenameObject
- we use just the high-level PyO3 bindings in their PyModule
struct, which PyO3 previously had as using PyModule_GetFilename
in the low-level FFI layer.
Looks like PyO3 switched over to PyModule_GetFilenameObject
in PyO3/pyo3#1425 which is destined for the omnibus 0.21 release, so if PyPy will add support for that in a later release, we can ask the PyO3 guys about relaxing the #[cfg(not(PyPy))]
on the method at an appropriate time.
In the mean time, I suppose the question for us is whether we want to accept #[cfg(PyPy)]
alternative paths within Qiskit itself, when we explicitly don't support PyPy in our wheel builds[^1]. I'm not super keen to degrade the tier-1 CPython version by using an uglier Python-space access to the __file__
attribute when PyO3 has a high-level method to access PyModule::filename
, but I'm also not super keen on manual #[cfg(PyPy)]
stuff for an interpreter we officially don't support.
[^1]: btw, when I said earlier about "we haven't discussed PyPy support", I meant along the lines of what we'd do in this sort of situation, i.e., would we make a best-effort-only attempt, or just abandon it at the first sign of trouble.
We don't really make a choice between PyModule_GetFilename and PyModule_GetFilenameObject - we use just the high-level PyO3 bindings in their PyModule struct, which PyO3 previously had as using PyModule_GetFilename in the low-level FFI layer.
Oh, right, I forgot that you had mentioned PyModule_GetFilename
and the original error message was just flagging filename()
. To me, it looks like PyO3 has been using GetFilenameObject
for a while but I might not be looking in the right place. In any case, it seems like PyO3 and PyPy will be aligned on using PyModule_GetFilenameObject
in the future and Qiskit should not need to make any change to its code for this.
In the mean time, I suppose the question for us is whether we want to accept #[cfg(PyPy)] alternative paths within Qiskit itself
I think we can just maintain the status quo for now of not considering PyPy until someone asks for it but consider making small changes for PyPy if they come up and are otherwise code quality improvements (like if Qiskit actually had been using a deprecated method when there was an alternative that also worked with PyPy, or looking into those test failures). It seems like PyO3 tries to keep good PyPy support and with Qiskit using abi3
that might be enough to keep it working.
Besides the test failures, I think the only action item is the documentation change I suggested which I implemented in https://github.com/Qiskit/documentation/pull/844.
In the documentation, three tiers of support are defined where support correlates to testing and and publishing binaries. It is stated that Qiskit could be built for other platforms. The discussion doesn't touch on what level of source code modification would be tolerated for running on other platforms, just which ones get tested and get binaries published. The text also distinguishes other interpreters as not supported but I am not sure if that is a stronger statement than just not being listed in the three tiers.
That all sounds like a plan to me, and thanks for updating the docs, Will.
Shall we close this issue as a "won't fix" for the time being, and re-evaluate in the future if we turn up a more pressing demand?
Sure, we can close this now. I will comment here if PyPy and PyO3 updates allow the Qiskit build to start working again.
Environment
What is happening?
Qiskit fails to build when using PyPy. Specifically, the qiskit_qasm3 crate fails with
How can we reproduce the issue?
Attempt to run
pip install .
with PyPy3.9.What should happen?
I am not sure :slightly_smiling_face: I know of this page specifying the different tiers of support for operating system versions, but I could not find anything stating if PyPy should be supported. I am just reporting that Qiskit 0.46 does build with PyPy and Qiskit 1.0 does not.
Any suggestions?
The issue is that
PyModule
does not have thefilename
function when using PyPy. The function was disabled here though there is not much explanation for why. Here is where the function is defined in PyO3.Also, I don't personally use Qiskit with PyPy. I was just porting the conda build from 0.46 to 1.0 and found this.