5

Is it possible to programmatically check if a wheel (whl) is compatible with the chosen Python installation before attempting to install?

I'm making an automated packages installer (packages needed for my Python project to work), and I need to only attempt to install compatible pkgs, so if there are errors, I know they are only from the compatible modules and I should see what happened (not errors also from incompatible pkgs, which I wouldn't care). Example: I'd have wheels for Python 3.5 and 3.7, and in a 3.5 installation, 3.7 wheels could not be tried to be installed.

I've tried pkginfo (https://pypi.org/project/pkginfo/), but on wheel.supported_platforms, it returns an empty array and I can't do anything with that (a wheel with "any" or with "win32" on their name in the platform part, returned an empty array, so I can't use that, it seems).

Also tried the output from python -m pip debug --verbose, but the following appears:

WARNING: This command is only meant for debugging. Do not use this with automation for parsing and getting these details, since the output and options of this command may change without no
tice.

This makes the command not possible to use, even though bellow that it prints the "Compatible tags", which more or less I could use to determine if a wheel is supported or not from its name. Example of those "Compatible tags" in a Python array:

['cp39-cp39-win_amd64', 'cp39-abi3-win_amd64', 'cp39-none-win_amd64', 'cp38-abi3-win_amd64', 'cp37-abi3-win_amd64', 'cp36-abi3-win_amd64', 'cp35-abi3-win_amd64', 'cp34-abi3-win_amd64', 'cp
33-abi3-win_amd64', 'cp32-abi3-win_amd64', 'py39-none-win_amd64', 'py3-none-win_amd64', 'py38-none-win_amd64', 'py37-none-win_amd64', 'py36-none-win_amd64', 'py35-none-win_amd64', 'py34-no
ne-win_amd64', 'py33-none-win_amd64', 'py32-none-win_amd64', 'py31-none-win_amd64', 'py30-none-win_amd64', 'cp39-none-any', 'py39-none-any', 'py3-none-any', 'py38-none-any', 'py37-none-any
', 'py36-none-any', 'py35-none-any', 'py34-none-any', 'py33-none-any', 'py32-none-any', 'py31-none-any', 'py30-none-any']

With, for example, "pyHook-1.5.1-cp36-cp36m-win32.whl", I could check the name and see if it's compatible or not (except because of the warning above...).

Any other ideas?

Thanks in advance for any help!

EDIT: I could go manually and pull things from the name and hard-code the some possibilities I see on documentation, like "win32" and "win_amd64" (as I did before), but then I'd need to know exactly all the possibilities that the parts of the name can have (I saw a cool expression on the documentation: "e.g." - which means there are more than the mentioned things) and have a lot of work on that. I was hoping there was already someone that had made such thing (maybe even Python itself has some way in any of its internal packages).

3
  • Does wheel use a Travis CI pipeline? Could you pull data from its builds and see what Python versions are being tested? Commented Mar 8, 2021 at 14:11
  • @JeffGruenbaum Hi. Thanks for the reply. Could you please give some examples of what you said? That's outside of my knowledge of Python haha.
    – Edw590
    Commented Mar 8, 2021 at 16:43
  • 1
    Travis CI is a testing tool which can be configured to run tests for certain python environments when changes are made to the repo. I'm looking at the wheel gituhub repo and it does not look like they use Travis CI. Taking a look at their github workflows, you can see what python versions are being tested here. You might be able to use this and check what was in this file for each release. It may require a bit of work to setup, so not sure if its the best solution. Commented Mar 8, 2021 at 17:49

1 Answer 1

6

You can do this using packaging.

pip install packaging

An example code to get the tags similar to how you got from pip would be:

from packaging.tags import sys_tags

tags = sys_tags()

print([str(tag) for tag in tags])
# ['cp39-cp39-manylinux_2_33_x86_64', 'cp39-cp39-manylinux_2_32_x86_64', 'cp39-cp39-manylinux_2_31_x86_64', ..... , 'py31-none-any', 'py30-none-any']

Of course, you can do much more things programmatically with the above variable tags:

>>> tags = sys_tags()
>>> for tag in list(tags)[:3]:
...     print(tag.interpreter, tag.abi, tag.platform)
... 
cp39 cp39 manylinux_2_33_x86_64
cp39 cp39 manylinux_2_32_x86_64
cp39 cp39 manylinux_2_31_x86_64

For more in-depth documentation, check: https://packaging.pypa.io/en/latest/tags.html#packaging.tags.sys_tags

3
  • It's not a universal method, since it requires a package that is limited in the supported Python versions, but I think it works for me. And still, it's a better way than being checking the output of the command manually. Thank you! Answer accepted!
    – Edw590
    Commented May 15, 2021 at 17:30
  • Though, if anyone (or you) finds a way to check without the need for the name, post the code here! There are packages with have in their name "py2.py3", and I think that would mean any Python2/3 version, or something. In anyway, I can't check correctly in those cases, because some packages with that in the name don't support all Python versions. Only some. Unless that means multiple versions supported. And I can't check it like that. A solution for that would be interesting (would also get me confused on which answer to accept xd).
    – Edw590
    Commented May 15, 2021 at 17:37
  • 1
    I think it should be possible to make a more universal implementation if someone is willing enough to put some work into it. All the code seems to be right here: github.com/pypa/packaging/blob/main/packaging/tags.py maybe someone could translate it into C/C++ maybe? It might not be as useful for a long time unless it's also maintained though.
    – chaitan94
    Commented May 15, 2021 at 18:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.