pypa / pip

The Python package installer
https://pip.pypa.io/
MIT License
9.46k stars 3.01k forks source link

Listing outdated packages fails #5757

Closed p0lm closed 2 years ago

p0lm commented 6 years ago

Environment

Description Uncaught exception occurs when checking for outdated packages, crashing pip. Apparently the version number is now a type, but does not support >-comparison.

Expected behavior Print a list of outdated packages

How to Reproduce Simply run pip list --outdated

Output

$ pip list --outdated
Exception:
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/pip/_internal/basecommand.py", line 141, in main
    status = self.run(options, args)
  File "/usr/lib/python3.7/site-packages/pip/_internal/commands/list.py", line 136, in run
    packages = self.get_outdated(packages, options)
  File "/usr/lib/python3.7/site-packages/pip/_internal/commands/list.py", line 147, in get_outdated
    dist for dist in self.iter_packages_latest_infos(packages, options)
  File "/usr/lib/python3.7/site-packages/pip/_internal/commands/list.py", line 148, in <listcomp>
    if dist.latest_version > dist.parsed_version
TypeError: '>' not supported between instances of 'Version' and 'Version'
althonos commented 5 years ago

I can reproduce this as well.

Environment

althonos commented 5 years ago

Here are my findings after investigating:

this error comes from dist.parsed_version and dist.latest_version not being the same type, one of which being a packaging.version and the other being a pip._vendor.packaging.version.Version (or possibly a .

Replacing the following lines in pip/_internal/index.py:

from pip._vendor.packaging import specifiers
from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.packaging.version import parse as parse_version

with

from packaging import specifiers
from packaging.utils import canonicalize_name
from packaging.version import parse as parse_version

fixes the issue, which makes me believe the vendoring process in pip/_vendor obfuscates the declaration of the Version class in a way it is declared twice independently. This will then cause the instance check to fail while comparing the classes of both versions.

benoit-pierre commented 5 years ago

Can you reproduce with a pristine version of pip (that is a version that is not unvendored)?

althonos commented 5 years ago

No, cloning the pypa/pip repository and running pip list --outdated works with that version. I assume the bug only occurs with DEBUNDLED=True.

benoit-pierre commented 5 years ago

IMHO, any unvendored pip is a (subtly) broken pip...

I can't reproduce this locally, with or without the distribution version of pip (I'm on Arch Linux too). What's the output of pip freeze --all?

althonos commented 5 years ago

@benoit-pierre : you'll laugh, but after trying stuff the error seems to be gone.

I'm not sure what made it go away, but I may have had an alternate pip or setuptools version installed in the user prefix that conflicted with the vendored dependencies.

benoit-pierre commented 5 years ago

I don't think a user installed pip/setuptools version is the cause for this, on the contrary, those vendored versions can only work better! Maybe a different version of packaging? I can easily break distrib pip by installing, say packaging==16 (and of course a vendored version of pip still works fine).

althonos commented 5 years ago

I can trigger the error again after installing setuptools in a user-install using:

$ pip install --user -U setuptools --force-reinstall

Installing setuptools also installs pkg_resources which may vendor its own packaging.version.Version I guess.

benoit-pierre commented 5 years ago

Yep, I can reproduce it too!

althonos commented 5 years ago

So installing setuptools from PyPI will install pkg_resources, which vendors its own packaging when you install it from PyPI... This will cause pkg_resources and pip to use two different packaging version, hence causing the instancecheck to fail.

I can't really see a way out of this though, unless preventing pkg_resources from vendoring packaging...

pfmoore commented 5 years ago

I guess the answer is that if you're de-vendoring, you need to de-vendor both pip and setuptools?

althonos commented 5 years ago

That happens when you let your package manager (and packagers) do everything for you, but if a user aggressively updates setuptools (for instance because the official repositories are lagging behind in term of updates) then the user will end up with a de-vendored pip and a vendored setuptools, causing this error to occur.

EDIT: not instance checking when comparing versions and relying on duck-typing would be preferable but I understand why you'd want to do that verification.

benoit-pierre commented 5 years ago

Don't use the distribution versions of setuptools/pkg_resources. Vendoring is there exactly to protect against this kind of issues. It really make no sense for a distribution like Arch Linux, whose pretty much always up-to-date, to unvendor pip/setuptools.

benoit-pierre commented 5 years ago

I think a new field should be added to the new issue template, or the version field should also mention how pip is installed (distribution package? from PyPi?).

althonos commented 5 years ago

Unfortunately, I think there may always be the case of an unwanted upgrade: if you run a pip install --user -U package where package has setuptools as a dependency, and you have an older setuptools (which may occur on a Debian, Fedora, whatever distro has a long enough release cycle) you may end up encountering this issue because you'll install the vendored setuptools with the unvendored pip.

chrahunt commented 5 years ago

Should we also add a note to the vendoring README with advice to help packagers avoid this situation?

pradyunsg commented 5 years ago

Sounds good to me!

pradyunsg commented 2 years ago

This issue looks like it's caused by changes that Debian made in their pip packaging. Please file a bug with Debian, with reportbug python3-pip (their reporting documentation). You can link to this issue in your bug report.

Closing this, since I don't think we can do anything about this on our end.