pip: pip install -U breaks dependencies
Environment
- pip version: 20.0.2
- Python version: 3.8.2
- OS: MacOS
- python installed by brew to avoid conflict with OS’s python.
$ uname -a
Darwin illbebachs-iMac 19.4.0 Darwin Kernel Version 19.4.0: Wed Mar 4 22:28:40 PST 2020; root:xnu-6153.101.6~15/RELEASE_X86_64 x86_64
Related Issue
#7744 Handle conflicts from installed packages when updating other packages
Description
pip install -U
breaks dependencies on installed packages, even when --upgrade-strategy=only-if-needed
is specified on the command line. In the script below, I create a clean environment using venv and install pylint. pip install -U
breaks dependencies of installed packages.
pip recognizes and reports the error regarding the dependency, but performs the upgrade anyway.
Expected behavior
pip should report the error and not perform the upgrade.
How to Reproduce
I ran the following script to demonstrate the error
#!/bin/bash
which python3.8
python3.8 --version
# setup a clean environment for testing
rm -rf clean_slate
python3.8 -m venv clean_slate
. clean_slate/bin/activate
which pip
which python
# upgrade basic packages to latest version
pip install --upgrade pip setuptools
pip --version
pip list
pip install pylint
pip list
pip check
pip list --outdated
# now perform the upgrade, where pip should fail
pip install --upgrade --upgrade-strategy=only-if-needed wrapt
pip check
Output
$ which python3.8
/usr/local/bin/python3.8
$ python3.8 --version
Python 3.8.2
$ rm -rf clean_slate
$ python3.8 -m venv clean_slate
$ . clean_slate/bin/activate
$ which pip
/Users/illbebach/clean_slate/bin/pip
$ which python
/Users/illbebach/clean_slate/bin/python
$ pip install --upgrade pip setuptools
... verbose output omitted ...
Successfully installed pip-20.0.2 setuptools-46.1.3
$ pip --version
pip 20.0.2 from /Users/illbebach/clean_slate/lib/python3.8/site-packages/pip (python 3.8)
$ pip list
Package Version
---------- -------
pip 20.0.2
setuptools 46.1.3
$ pip install pylint
... verbose output omitted ...
Successfully installed astroid-2.3.3 isort-4.3.21 lazy-object-proxy-1.4.3 mccabe-0.6.1 pylint-2.4.4 six-1.14.0 wrapt-1.11.2
$ pip list
Package Version
----------------- -------
astroid 2.3.3
isort 4.3.21
lazy-object-proxy 1.4.3
mccabe 0.6.1
pip 20.0.2
pylint 2.4.4
setuptools 46.1.3
six 1.14.0
wrapt 1.11.2
$ pip check
No broken requirements found.
$ pip list --outdated
Package Version Latest Type
------- ------- ------ -----
wrapt 1.11.2 1.12.1 sdist
$ pip install --upgrade --upgrade-strategy=only-if-needed wrapt
Collecting wrapt
Using cached wrapt-1.12.1.tar.gz (27 kB)
ERROR: astroid 2.3.3 has requirement wrapt==1.11.*, but you'll have wrapt 1.12.1 which is incompatible.
Installing collected packages: wrapt
Attempting uninstall: wrapt
Found existing installation: wrapt 1.11.2
Uninstalling wrapt-1.11.2:
Successfully uninstalled wrapt-1.11.2
Running setup.py install for wrapt: started
Running setup.py install for wrapt: finished with status 'done'
Successfully installed wrapt-1.12.1
$ pip check
astroid 2.3.3 has requirement wrapt==1.11.*, but you have wrapt 1.12.1.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (12 by maintainers)
Forgive the lateness of my reply. During the discussion, it quickly became apparent I do not have a full context of the history of this issue. That said, several times above, others stated “pip does not know what the user wants”. To me, “what the user wants” can be stated in this simplistic statement:
Update everything to the newest version possible, without breaking anything.
If I were king, I would specify the proper behavior be much as the description of poetry, as mentioned by @WSLUser, behaves. Without other inputs, “pip install -U” should upgrade all installed packages, then give a note stating what happened. “pip install -U” is my typical use-case where I periodically want to update my system. A contrived example output would be
Perhaps if —verbose is specified, for each package1,2,… above, print the newly installed version, the latest available version, and a possibly long list of packages which caused the conflict.
Even if the user specifies “pip install —update A B”, it is possible that A or B cannot be updated to the latest available, due to conflicts with installed packages. In that case, it seems to me, the proper thing to do is still “Update A and B to the newest version possible, without breaking anything”.
I recently became aware of the pipdeptree package, which I find helpful in seeing dependencies among packages.
Thank you all for adding so much context to the discussion. I was not aware of the longstanding issues or the broader context.
I think both of those concerns are in-scope for #7744.
Honestly, this is a known issue with pip’s current resolver (see #988) and grant funded work is being undertaken right now to fix the broader issue.
I’m personally inclined to close this issue and classify it as “will be tackled as part of funded work on #988” + duplicate of #7744.
@uranusjr I think @sbidoul is suggesting augmenting/improving the
REQUESTED
file, to include that information – about what the user requested – to serve as a distributed manifest.This was (incidentally) discussed quite extensively in discussions on implementing the new dependency resolver (notes from last week, search for installed packages for the relevant parts; follow-up discussion is around here). The opinions are conflicting, unfortunately, and has a lot of technical and UX implications.