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'
I can reproduce this as well.
Environment
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.
Can you reproduce with a pristine version of pip (that is a version that is not unvendored)?
No, cloning the pypa/pip
repository and running pip list --outdated
works with that version. I assume the bug only occurs with DEBUNDLED=True
.
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
?
@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.
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).
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.
Yep, I can reproduce it too!
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
...
I guess the answer is that if you're de-vendoring, you need to de-vendor both pip and setuptools?
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.
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.
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?).
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
.
Should we also add a note to the vendoring README with advice to help packagers avoid this situation?
Sounds good to me!
sorry, I do not understand the discussion above in every detail.
I see the problem described above on my system running Devuan/Beowulf what in the Python-World is identical to Debian/Buster(stable).
sudo apt install python3-pip
follwoed by pip3 list --outdated
seems to be enough to reproduce the error:
Exception:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/pip/_internal/cli/base_command.py", line 143, in main
status = self.run(options, args)
File "/usr/lib/python3/dist-packages/pip/_internal/commands/list.py", line 138, in run
packages = self.get_outdated(packages, options)
File "/usr/lib/python3/dist-packages/pip/_internal/commands/list.py", line 149, in get_outdated
dist for dist in self.iter_packages_latest_infos(packages, options)
File "/usr/lib/python3/dist-packages/pip/_internal/commands/list.py", line 150, in <listcomp>
if dist.latest_version > dist.parsed_version
TypeError: '>' not supported between instances of 'Version' and 'Version'
I never installed anything outside the Debian Package Manager. So if I understand the discussion above correctly the package manager made a mistake. Is this correct?