I would like to open a discussion about recognizing, managing, distributing and installing non-ABI-stable Python wheels (a.k.a. wheels created with alpha/beta versions of Python), with the goal to speedup wheel deployment for new Python versions.
In this topic start I will expand on the current situation and problem, propose potential solution and give some context. But I would mainly like to open a discussion on this topic.
The current situation and problem
Wheels are extremely important for the Python ecosystem, and especially the scientific subsection. Newer Python versions offer many benefits, like new features and faster performance. With the release of a new Python version, for many packages wheels are unfortunately not immediately available for that version.
This is a problem with many aspects, and in this feature request a system is proposed to partly but significant improve this situation.
The Python annual release cycle, as described in PEP 602, knows 3 phases. In the Alpha phase new features are added and bugs are fixed, during 7 months. The 3-month Beta phase allows for bug fixes. The 2-month release candidate phase is not clearly described in PEP 602, but practically only essential bugs and security issues are fixed. Historically, it also starts the ABI-stable phase for that minor Python version (Python 3.10.0rc1 | 3.11.0rc1).
This 2-month phase is where currently the wheel-building race starts for many projects. And while for a single project two months should be more than enough, many projects depend on many other projects. On the scientific stack, for example, Cython needs to come in first, then NumPy, then SciPy and Pandas, then scikit-learn and statsmodels. And if you projects depends on one of the latter, this two-month window gets really short.
In this window, not only wheels need to be successfully build for the new Python version, but also need to be included in a tagged release. For many projects, this means backporting to a maintenance branch and tagging a new patch release.
Since amending PEP 602 would be a major undertaking and have many side-effects on the ecosystem, this feature request proposes a system for managing wheels on PyPI created with non-ABI-stable Python versions.
A potential solution
When wheels build with non-ABI-stable Python releases are handled differently in pip, it would be possible to allow (and encourage) uploading those wheels, without letting users accidentally install them. In this system where non-ABI-stable wheels can be uploaded, they should (by default) only be installed on the exact same Python release on which they are generated. Then, options could then be added to loosen this strict version requirement, for development purposes (including testing and CI).
The steps to create such a system could look like this:
- The exact Python version with which a wheel is build needs to be recognizable. Some help from wheel is needed here, and maybe the wheel specification needs to be modified.
- pip should (by default) install wheels generated with an Alpha or Beta Python version only on that exact Alpha or Beta Python version.
- A CLI and/or Environment variable needs to be introduce to loosen the strict version requirement above, to make it more usable for CI configurations. This could be called
--experimental
for example. Options could be0
(the default) which only installs the wheels on the exact same Python version.1
could mean only install wheels that are generated with the exact same or an earlier Python version (so on Python 3.12b1 wheels from Python 3.12b0 can be installed, but not visa versa), while2
could mean install wheels from all Python versions with the same minor version (so install all 3.12 wheels).
3.1. When using option1
or2
and not the exact same Python version is present, a note/warning should be always printed. - Documentation and tests needs to be added.
Then, some optional, but useful extensions for the ecosystem could be implemented:
- The PyPI website could display an experimental tag in the Download files tab, together with the exact Python version with which the wheel was generated.
- cibuildwheel could be update to handle this functionally and allow control over it.
Implementing this, the wheel-building period could be extended from the current 2-month release candidate phase, to the full 12-month development cycle of Python. Which will increase wheel-readyness for a new stable Python version hugely.
Alternative Solutions
Amending PEP 602 would be a major undertaking and have many side-effects on the ecosystem, so is not preferable.
Apart from extending the wheel-distribution period, another angle could be a speedup in getting wheels on PyPI. One option for this could be allowing (periodically) generated wheels from a development branch. This way dependent projects don’t have to wait for a backport and stable release to be tagged. This solution could work in conjunction with the proposed solution in this feature request.
Additional context
Thanks to cibuildwheel, and it’s increasing adoption, Python 3.12 wheels are in a better shape then with earlier Python releases. Still it’s a race against the clock:
- Cython had Python 3.11 wheels since 0.29.30, released on May 17, 2022, still in the beta period. The next release was in 0.29.32 on July 19th, also in the beta period. Since then no wheels have been released, so a warning that we’re testing with Cython beta wheels would be useful (as proposed in 3.1).
- With the system above, releasing experimental wheels in the Alpha phase could also become more feasible.
- NumPy had their first 3.11 wheels with the 1.23.2 release on August 14th, just a week into the release candidate phase (Aug 8). This started the cycle for other projects, like Pandas and SciPy.
- Pandas followed with their wheels on September 19th with the 1.5.0 release.
- SciPy followed with their 1.9.2 release, on October 8th.
- statsmodels and scikit-learn don’t have 3.12 wheels available.
Discussion
So this are just some thoughts and ideas, with this topic start I would like to open the discussion on how we can improve this situation. I look forward to hearing everyone’s thoughts!