-
Notifications
You must be signed in to change notification settings - Fork 3k
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
pip wheels (from ensurepip) show nonexistant entry_points in importlib.metadata #10355
Comments
The problem is of course that setup.py is choosing its list of console_scripts dynamically based on the python version in which it is run: Lines 70 to 73 in a974526
So the scripts created at install time and the metadata recorded in the wheel (pip-*.dist-info\entry_points.txt) do not necessarily agree. I'm not sure what the best resolution is (create a new entry_points.txt when actually doing the install/creating the entry_point launchers? somehow skip the version specific pip3x entry_points when building a "generic" wheel, i.e. just "pip" and "pip3" for a .py3. wheel, and just "pip" for a .py2.py3 wheel (which isn't done anymore, so whatever)? I don't know enough about how the tags for the wheel get chosen (I assume it's related to the classifiers") to know how setup.py could know which ones to mention when creating a wheel... Or maybe the wrong metadata is not that important, and this can just be a WONTFIX. But it seemed weird enough to be worth mentioning. |
Pip has special treatment to itself and actually does not respect the listed entry points, but creates IIRC there was talk we should probably remove the confusing hard-coded |
I don't quite understand what you mean, since If the latter, one could just do a hack like entry_points={
"console_scripts": [
"pip=pip._internal.cli.main:main",
] + ([] if 'bdist_wheel' in sys.argv else [
"pip{}=pip._internal.cli.main:main".format(sys.version_info[0]),
"pip{}.{}=pip._internal.cli.main:main".format(*sys.version_info[:2]),
])
}, Admittedly not a thing of beauty, but it does install all 3 for |
Yes it does. What I meant was if we’re going to remove anything, it’d be from the wheels we build for distribution (e.g. to PyPI). But in the mean time, if the user builds from source (e.g. I think one way to do it is instead of producing version-independent wheels ( If this sounds complex, it indeed is. And I’m not sure if it’s even possible without either hacks in |
I think if we want to solve this issue "properly", we have to switch to just having a But I don't want to pile more hacks on to cater for this - the existing approach is a hack that delivers something that (as I understand it) our existing downstream consumers can work with. If new consumers, like the OP, cannot work around the existing hack, we can remove it (and inform our downstream that they will now have to handle this themselves) or retain it (and inform the new consumers that it's needed and they'll have to deal with it). Making ever more complex hacks each time someone new comes along with a use case simply isn't sustainable IMO. But as @uranusjr says, none of the pip maintainers think this is a particularly important issue, so it'll be up to someone else to make a PR for this, ensure that any solution is acceptable both to pip and to downstream, etc. |
Wait, we are generating the correct scripts when installing. OP's concern is that those can mismatch with what's in entry_points.txt. |
Yes, that's because we generate versioned values in I'm saying that to be correct, our entry point should just be |
If that's true, it sure looks like they'd already break frequently already. Sampling the assortment of versions I happen to have handy, we appear to be 1/5
It appears @uranusjr updated to 3.9 some time in the last few days, because the very latest pip-21.2.4-py3-none-any.whl on https://pypi.org/project/pip/21.2.4/ now has pip3.9 (so when/if 21.2.4 gets into the 3.9 branch, maybe 3.9.7 will match up). But in 3.10 it won't. Now, it seems that ensurepip uses pip to install itself (by adding pip's wheel to sys.path, in order to invoke the not-yet-installed version to install itself). So that ought to (and seems to) get the special-casing and produce the right scripts. But if someone else is following the entry_point.txt, they'll get some kind of versioned scripts, but seemingly more often than not the wrong ones (even when using "matching" cpython and pip versions). That said, this issues's not that critical to me either. I just stumbled across it because I was converting this cmake-import generator from -- What triggered me to even be messing with all this was that pip 21.2 is now released (with packaging.tags 21.0), and both are merged to the python 3.10 branch, bpo-38989 is solved, which means there will soon be a python > 3.7.9 that again works if called in an MSVC cross-compiling environment again. Hooray 🎈 🎉 🍰! |
Cool. Given that everyone on this thread doesn't think this is important or worth fixing, let's close this? |
From my understanding, Linux distributions don’t use ensurepip to install pip, but build pip from source. This is usually for policy reasons (most of them can’t distribute binary packages, and wheels are categorised as such), but as a result they are never affected by those entry points.
Actually I was just building on a different computer 🙂 |
I've already given a "thumbs up" to @pradyunsg's comment suggesting we just close this, but I'm curious. If that's the case, why would it make any difference to anyone if we just removed the versioned entry points altogether from pip's |
Because when the distributors build pip on their own (either by wheel or |
OK, cool. If anyone cared enough, I guess we could change |
Yeah, I’m definitely not going to work on it myself, but also not going to stop anyone if they feel strong enough about this. |
Actually, with one more tweak that sounds like it could be a pretty clean answer. The tweak would be to also tie the I'm just not sure how to control [bdist_wheel]python_tag dynamically when running
and this works, but I haven't figured out how I can substitute a dynamic value like |
I'm -1 on setting the python tag. There's nothing about the resulting wheel that's specific to the Python version - an entry point of pip3.9 is completely valid in a wheel built and used on Python 3.8 - it may be a confusing name to use, but it's entirely legitimate. I'd consider setting the Python tag to be a misuse of the tag system, TBH. |
Is there an actual user-facing problem, originating from the mismatched entry points declaration? |
Well, half-legitimate - it would be legitimate to create, but it doesn't actually get created because pip special-cases itself. So it depends on whether you're using the metadata to know what to create (it would be fine, if odd) or if you're using it to know what to look for/copy (it refers to a file that isn't there).
my (custom) conan generator to enumerate the package entry_points for python tools (things like sphinx) which it has installed in a venv, and write corresponding CMake add_executable(IMPORTED) targets that can be used to call easily them during the build or tests failed. This is just because it threw a FileNotFound exception while trying to get an absolute path for the corresponding executable (because there wasn't one for the wrongly-versioned name). I have already fixed said generator to just catch that exception, print a warning about the nonexistant script, and continue with any entry_points that do exist. So... yes, but not a very serious one, and it's worked-around now. |
I know this is an old issue, but after a long investigation as to why my The inclusion of the I'll demonstrate the bug using pip 22.3.1 (which has $ which pip3.10
/opt/homebrew/bin/pip3.10
$ which pip3.9
/opt/homebrew/bin/pip3.9
$ pip3.9 install -U --no-cache --force-reinstall pip
Collecting pip
Downloading pip-22.3.1-py3-none-any.whl (2.1 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 24.2 MB/s eta 0:00:00
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 22.3.1
Uninstalling pip-22.3.1:
Successfully uninstalled pip-22.3.1
Successfully installed pip-22.3.1
$ ls -l /opt/homebrew/bin/pip3.10
ls: /opt/homebrew/bin/pip3.10: No such file or directory This is happening in the uninstallation phase (which happens on upgrade as well). We can verify that with: $ pip3.11 uninstall pip
Found existing installation: pip 22.3.1
Uninstalling pip-22.3.1:
Would remove:
/tmp/delme/bin/pip
/tmp/delme/bin/pip3
/tmp/delme/bin/pip3.10 # <----
/tmp/delme/bin/pip3.11
/tmp/delme/lib/python3.11/site-packages/pip-22.3.1.dist-info/*
/tmp/delme/lib/python3.11/site-packages/pip/*
Proceed (Y/n)? This seems to me like a pretty big unintentional consequence of that extra entry. If it were just our CI setup, fine, but it's a problem on system installs as well. One can argue that |
Ultimately, the solution to this is #3164 (deprecate the versioned entry points). |
It looks like we can just safely remove the version-specific console_scripts of pip today FWIW. The entry point that triggers the special case handling is pip/src/pip/_internal/operations/install/wheel.py Lines 316 to 346 in 90f51db
|
Yea, that's a bug due to the |
I wonder if we should just get rid of them all; we’ve always wanted to delete them anyway, are there reasons we can’t change the detection to “we are installing a package called |
I'm running the version with that patch, and have even hard-coded removing it there. It doesn't seem to be at that stage (and not limited to |
The code calculating the files to remove is |
Description
I was working on some code (a conan generator to write cmake
add_executable(... IMPORTED)
bindings based on importlib.metadata.entry_points), and noticed something odd - there was an entry point for pip3.8 showing up that didn't actually have a corresponding launcher pip3.8.exe (since I was/am stuck using python 3.7 to avoid #8649 until a cpython release picks up pip 21.2, the actual launcher was pip3.7.exe).Expected behavior
importlib.metadata.Distribution.entry_points will correspond to the entry_point launchers that actually exist.
pip version
20.2.3-21.2.4
Python version
3.9.4
OS
Windows
How to Reproduce
note the presence of
EntryPoint(name='pip3.8', value='pip._internal.cli.main:main', group='console_scripts')
, even though this is python 3.9, not 3.8.Output
[EntryPoint(name='pip', value='pip._internal.cli.main:main', group='console_scripts'), EntryPoint(name='pip3', value='pip._internal.cli.main:main', group='console_scripts'), EntryPoint(name='pip3.8', value='pip._internal.cli.main:main', group='console_scripts')]
entry_points.txt
The wheel for 21.2.4 still seems to show the same sort of thing going on: https://files.pythonhosted.org/packages/ca/31/b88ef447d595963c01060998cb329251648acf4a067721b0452c45527eb8/pip-21.2.4-py3-none-any.whl (though there it's pip3.9 that is present)
Code of Conduct
The text was updated successfully, but these errors were encountered: