I recently stumbled across this thread about the python tag part of PEP 425. As a result of that conversation, I learned that python tags in the form py2x or py3x indicate compatibility with at least Python 2.x or 3.x, respectively.
This got me thinking whether a simple python_requires like >= 3.4 should be reflected with a py34 tag in the built wheel.
PEP 425 does seem to address this:
What tag do I use if my distribution uses a feature exclusive to the newest version of Python?
Compatibility tags aid installers in selecting the most compatible build of a single version of a distribution. For example, when there is no Python 3.3 compatible build of beaglevote-1.2.0 (it uses a Python 3.4 exclusive feature) it may still use the py3-none-any tag instead of the py34-none-any tag. A Python 3.3 user must combine other qualifiers, such as a requirement for the older release beaglevote-1.1.0 that does not use the new feature, to get a compatible build.
Why wouldn’t I want to use the more specific py34 tag though? Wouldn’t it make sense to use the more specific tag so installers don’t even bother downloading a potentially incompatible wheel?
Because no PEP specifies that py34must be considered supported by any version of Python other than Python 3.4. Now in practice it is thanks to packaging.tags printing out all Python versions from the version you’re installing for down to 3.0, but that’s convention and not a standard to rely on.
Plus the requires-python metadata is exposed in the wheel metadata itself which PyPI and the Simple Index expose directly. And so installers don’t really need this sort of detail expressed in the filename as they get it elsewhere in it’s full form.
“py34.abi3” is certainly supposed to mean “compatible with the stable ABI as defined in Python 3.4 and later”, so rejecting such a wheel as incompatible with later Python versions definitely wouldn’t be complying with the intent of the specification, even if it could be argued it was compliant with a potential reading of the letter of it.
I think the main reason people don’t make wheel tags like that is simpler: if Python-Requires is set correctly, it doesn’t matter if the more general wheel tag is used, so the motivation to spend time enhancing the tag generation code is weak.
Ah I didn’t realize PyPI exposes that. I thought installers had to download wheels to get that metadata and setting the wheel tags would be an optimization to avoid that.
The main reason python_requires is handled separately from wheel tags is that python_requires applies to sdists, not just wheels. Normally, if the latest package version doesn’t have a wheel that matches the target environment, then pip will still choose that version and then download the sdist to build locally. But python_requires applies to the entire package version, and tells pip to skip that version entirely and use an older one.
Possibly we should have a more systematic way to describe supported environments for sdists, but so far there hasn’t been much need.