Closed balloob closed 1 year ago
I can not reproduce, I get ResolutionImpossible
pretty quickly (bar download time).
I tested on Ubuntu 20.04.3 LTS and changed the commands a little bit so they could be easily repeated without causing the state of the environment to change:
git clone https://www.gitHub.com/home-assistant/core home-assistant-core
cd home-assistant-core
python3.10 -m venv .venv
source .venv/bin/activate
python -m pip install pip --upgrade
python -m pip download -r requirements_all.txt -d downloads
The ResolutionImpossible
seems to related to aiohttp
which is set to 3.8.1
in the top level requirements and constraints file but at least one of the requirements discord-py
specifies it as aiohttp<3.8.0 and >=3.6.0
. Full conflict error I get:
The conflict is caused by:
The user requested aiohttp==3.8.1
adax-local 0.1.3 depends on aiohttp>=3.0.6
accuweather 0.3.0 depends on aiohttp
adax 0.2.0 depends on aiohttp>=3.0.6
adguardhome 0.5.0 depends on aiohttp>=3.0.0
advantage-air 0.2.5 depends on aiohttp
afsapi 0.0.4 depends on aiohttp>=3.3.2
aio-geojson-geonetnz-quakes 0.13 depends on aiohttp<4 and >=3.7.4
aio-geojson-geonetnz-volcano 0.6 depends on aiohttp<4 and >=3.7.4
aio-geojson-nsw-rfs-incidents 0.4 depends on aiohttp<4 and >=3.7.4
aioambient 2021.11.0 depends on aiohttp<4.0.0 and >=3.7.4
aioaseko 0.0.1 depends on aiohttp
aioazuredevops 1.3.5 depends on aiohttp>=3.6.2
aiobotocore 1.2.2 depends on aiohttp>=3.3.1
aioeafm 0.1.2 depends on aiohttp<4.0.0 and >=3.6.1
aioeagle 1.1.0 depends on aiohttp
aioemonitor 1.0.5 depends on aiohttp>=3.7.0
aioflo 2021.11.0 depends on aiohttp<4.0.0 and >=3.7.4
aiogithubapi 21.11.0 depends on aiohttp<4.0 and >=3.6.1
aioguardian 2021.11.0 depends on aiohttp<4.0.0 and >=3.7.4post0
aioharmony 0.2.9 depends on aiohttp
aiohttp-cors 0.7.0 depends on aiohttp>=1.1
aiohue 3.0.11 depends on aiohttp
aiohwenergy 0.6.0 depends on aiohttp
aiolookin 0.1.0 depends on aiohttp>=3.7.4
aiolyric 1.0.8 depends on aiohttp>=3.7.3
aiomodernforms 0.1.8 depends on aiohttp>=3.0.0
aiomusiccast 0.14.3 depends on aiohttp<4.0.0 and >=3.7.4
aionanoleaf 0.1.1 depends on aiohttp
aionotion 3.0.2 depends on aiohttp<4.0.0 and >=3.7.4
aiopvapi 1.6.19 depends on aiohttp<4 and >=3.7.4
aiopvpc 3.0.0 depends on aiohttp>=3.7.4.post0
aiorecollect 1.0.8 depends on aiohttp<4.0.0 and >=3.7.4
aioridwell 2021.12.2 depends on aiohttp>=3.8.0
aioshelly 1.0.7 depends on aiohttp
aiosteamist 0.3.1 depends on aiohttp<4.0.0 and >=3.8.1
aiosyncthing 0.5.1 depends on aiohttp>=3.7.4
aiotractive 0.5.2 depends on aiohttp>=3.7.4
aiounifi 29 depends on aiohttp
aiowatttime 0.1.1 depends on aiohttp<4.0.0 and >=3.7.4
aioymaps 1.2.2 depends on aiohttp>=3.0.0
airly 1.1.0 depends on aiohttp>=3.5.4
airthings-cloud 0.1.0 depends on aiohttp>=3.0.6
alpha-vantage 2.3.1 depends on aiohttp
ambee 0.4.0 depends on aiohttp>=3.0.0
ambiclimate 0.2.1 depends on aiohttp>=3.0.6
asmog 0.0.6 depends on aiohttp
async-upnp-client 0.23.3 depends on aiohttp>=3.7.4
asyncpysupla 0.0.5 depends on aiohttp
blebox-uniapi 1.3.3 depends on aiohttp>=3
bond-api 0.1.15 depends on aiohttp>=3.6.1
brunt 1.1.1 depends on aiohttp
bsblan 0.4.0 depends on aiohttp>=3.0.0
connect-box 0.2.8 depends on aiohttp
coronavirus 1.1.1 depends on aiohttp>=3.0.0
crownstone-cloud 1.4.9 depends on aiohttp~=3.7
crownstone-sse 2.0.3 depends on aiohttp~=3.7
directv 0.4.0 depends on aiohttp>=3.6.2
discord-py 1.7.3 depends on aiohttp<3.8.0 and >=3.6.0
The user requested (constraint) aiohttp==3.8.1
Thanks for filing this @balloob! ^>^
While I haven't started using Home Assistant yet, it's been on my radar and I appreciate the work that you and other volunteers who have worked on it, have put into it!
Much like @notatallshaw, I'm unable to reproduce this with pip 21.3.1 on MacOS, with a ResolutionImpossible
error after 4m 4s with unpopulated cache (i.e. everything had to download). With a populated cache, that takes 2m 0s.
The error is that exact same as @notatallshaw, as far as I can tell.
The conflict is caused by:
The user requested aiohttp==3.8.1
adax-local 0.1.3 depends on aiohttp>=3.0.6
accuweather 0.3.0 depends on aiohttp
adax 0.2.0 depends on aiohttp>=3.0.6
adguardhome 0.5.0 depends on aiohttp>=3.0.0
advantage-air 0.2.5 depends on aiohttp
afsapi 0.0.4 depends on aiohttp>=3.3.2
aio-geojson-geonetnz-quakes 0.13 depends on aiohttp<4 and >=3.7.4
aio-geojson-geonetnz-volcano 0.6 depends on aiohttp<4 and >=3.7.4
aio-geojson-nsw-rfs-incidents 0.4 depends on aiohttp<4 and >=3.7.4
aioambient 2021.11.0 depends on aiohttp<4.0.0 and >=3.7.4
aioaseko 0.0.1 depends on aiohttp
aioazuredevops 1.3.5 depends on aiohttp>=3.6.2
aiobotocore 1.2.2 depends on aiohttp>=3.3.1
aioeafm 0.1.2 depends on aiohttp<4.0.0 and >=3.6.1
aioeagle 1.1.0 depends on aiohttp
aioemonitor 1.0.5 depends on aiohttp>=3.7.0
aioflo 2021.11.0 depends on aiohttp<4.0.0 and >=3.7.4
aiogithubapi 21.11.0 depends on aiohttp<4.0 and >=3.6.1
aioguardian 2021.11.0 depends on aiohttp<4.0.0 and >=3.7.4post0
aioharmony 0.2.9 depends on aiohttp
aiohttp-cors 0.7.0 depends on aiohttp>=1.1
aiohue 3.0.11 depends on aiohttp
aiohwenergy 0.6.0 depends on aiohttp
aiolookin 0.1.0 depends on aiohttp>=3.7.4
aiolyric 1.0.8 depends on aiohttp>=3.7.3
aiomodernforms 0.1.8 depends on aiohttp>=3.0.0
aiomusiccast 0.14.3 depends on aiohttp<4.0.0 and >=3.7.4
aionanoleaf 0.1.1 depends on aiohttp
aionotion 3.0.2 depends on aiohttp<4.0.0 and >=3.7.4
aiopvapi 1.6.19 depends on aiohttp<4 and >=3.7.4
aiopvpc 3.0.0 depends on aiohttp>=3.7.4.post0
aiorecollect 1.0.8 depends on aiohttp<4.0.0 and >=3.7.4
aioridwell 2021.12.2 depends on aiohttp>=3.8.0
aioshelly 1.0.7 depends on aiohttp
aiosteamist 0.3.1 depends on aiohttp<4.0.0 and >=3.8.1
aiosyncthing 0.5.1 depends on aiohttp>=3.7.4
aiotractive 0.5.2 depends on aiohttp>=3.7.4
aiounifi 29 depends on aiohttp
aiowatttime 0.1.1 depends on aiohttp<4.0.0 and >=3.7.4
aioymaps 1.2.2 depends on aiohttp>=3.0.0
airly 1.1.0 depends on aiohttp>=3.5.4
airthings-cloud 0.1.0 depends on aiohttp>=3.0.6
alpha-vantage 2.3.1 depends on aiohttp
ambee 0.4.0 depends on aiohttp>=3.0.0
ambiclimate 0.2.1 depends on aiohttp>=3.0.6
asmog 0.0.6 depends on aiohttp
async-upnp-client 0.23.3 depends on aiohttp>=3.7.4
asyncpysupla 0.0.5 depends on aiohttp
blebox-uniapi 1.3.3 depends on aiohttp>=3
bond-api 0.1.15 depends on aiohttp>=3.6.1
brunt 1.1.1 depends on aiohttp
bsblan 0.4.0 depends on aiohttp>=3.0.0
connect-box 0.2.8 depends on aiohttp
coronavirus 1.1.1 depends on aiohttp>=3.0.0
crownstone-cloud 1.4.9 depends on aiohttp~=3.7
crownstone-sse 2.0.3 depends on aiohttp~=3.7
directv 0.4.0 depends on aiohttp>=3.6.2
discord-py 1.7.3 depends on aiohttp<3.8.0 and >=3.6.0
The user requested (constraint) aiohttp==3.8.1
To fix this you could try to:
1. loosen the range of package versions you've specified
2. remove package versions to allow pip attempt to solve the dependency conflict
You are likely getting a warning from the legacy resolver about dependency conflicts as well -- it just does not fail when it encounters a dependency conflict.
I experimented to see if I could "fix" the ResolutionImpossible
, I tried slowly loosening the requirements to allow pip to find compatible versions. This revealed a lot of conflicting requirements based on aiohttp
, websockets
, click
, boto3
, etc..
Here are two cases I found which seemed unresolvable:
mycroftapi==2.0
depends on the very old websocket-client==0.44.0
. But mycroftapi
but it hasn't been updated in over 3 years and the home page link returns a 404: https://pypi.org/project/mycroftapi/ . Rather than trying to find very old versions of the 4 projects that require newer than websocket-client==0.44.0
I just dropped the mycroftapi
requirement.pysmarty
0.8 requires pymodbus==1.5.2
and pystiebeleltron
0.0.1.dev2 requires pymodbus>=2.1.0
. This doesn't seem resolvable as pysmarty
doesn't seem to be updated any more (no update in 2-3 years) and pystiebeleltron
only has 2 non-release versions and no updates in over 1 year. I drop[ed pystiebeleltron
from the requirements as it is an unreleased version.I continued loosening requirements but unfortunately this eventually led to very long backtracking times. I used an experimental version of Pip I have which implements backjumping to try and speed up these very complex scenarios and continued trying to loosen the requirements.
Eventually I was able to find a set of requirements that didn't conflict (minus the two packages above), and after switching to Python 3.9 to build them (I could not get homeassistant-pyozw
to build on 3.10). Here is the output of pip freeze, perhaps you can compare it to a pip freeze in a working environment you have, and update them 1 at a time to see what causes conflicts:
Actually I rebuilt the requirements files with the above freeze information.
Using these and fixing/removing the constraints file you can install using pip 21.3.1. Though you will need to figure out which libraries are too old for your requirements and look at why they have conflicts by updating them and see what the conflicts are.
Here is a diff on the requirements_all.txt
:
-PyRMVtransport==0.3.3
+PyRMVtransport==0.3.2
-aioambient==2021.11.0
+aioambient==2.0.0
-aiobotocore==1.2.2
+aiobotocore==2.1.0
-aioridwell==2021.12.2
+aioridwell==2021.10.0
-aiosteamist==0.3.1
+aiosteamist==0.1.0
-boto3==1.16.52
+boto3==1.20.24
-hole==0.7.0
+hole==0.6.0
-# homeassistant.components.mycroft
-mycroftapi==2.0
-open-meteo==0.2.1
+open-meteo==0.0.1
-py17track==2021.12.2
+py17track==2021.12.0
-pyicloud==0.10.2
+pyicloud==0.7.3
-pymodbus==2.5.3
+pymodbus==1.5.2
-pyoverkiz==1.1.0
+pyoverkiz==1.1.1
-pysml==0.0.6
+pysml==0.0.5
-# homeassistant.components.stiebel_eltron
-pystiebeleltron==0.0.1.dev2
-pytile==2021.12.0
+pytile==2021.10.0
-simplisafe-python==2021.12.2
+simplisafe-python==2021.11.2
-systembridge==2.2.3
+systembridge==1.1.5
-vallox-websocket-api==2.8.1
+vallox-websocket-api==2.6.0
And the diff on requirements.txt
:
-aiohttp==3.8.1
+aiohttp==3.7.4.post0
-async_timeout==4.0.2
+async_timeout==3.0.1
-pip>=8.0.3,<20.3
Thanks for digging in!
Is there a place where we can find your experimental pip version?
We definitely have some old packages around for integrations that haven't been touched in years. Sometimes integration requirements get disabled when we raise our minimum Python version. Looks like we'll have to do so here too.
It's too bad that our lax handling of dependencies of our integrations is finally catching up on us. It means we'll need to pro-actively take care of it. Ccurrently we do it once an issue is raised that something doesn't work.
The requirements diff doesn't look too bad although I would hate to have to downgrade things (because it means we can't move forward!)
You can ~blame~ reach out to packages like discord-py regarding some of the pain here, asking them to remove the relevant problematic pins. You're basically already seeing the problems described in https://iscinumpy.dev/post/bound-version-constraints/#tldr.
If those packages are using poetry or using something like ~=
without good reason, point them to the aforementioned blog post.
Is there a place where we can find your experimental pip version?
Yes but it's not stable so I don't guarantee anything about it.
To explain a little bit about what it's doing, a backtracking optimization landed on pip 21.3: https://github.com/pypa/pip/issues/10479 . This optimization is very good at handling the cases where the solution seems "obvious", i.e. A and B don't agree on what version C should be used, so it checks different versions of A and B until they do. However it's not very good at situations where you add a dependency A and it conflicts with multiple preexisting dependencies e.g. X, Y, and Z.
In the experimental version I am testing I use backjumping in an attempt to make those scenarios more solvable. But it still has many limitations and my implementation at the moment is very hacky and I've not verified it other than testing it in complex scenarios and seeing how it performs.
Here's a tag of the version I used to help here: https://github.com/notatallshaw/pip/tree/homeassistant . I think you can install it like so: python -m pip install git+https://github.com/notatallshaw/pip@homeassistant
It also only helps to a certain extent, allowing to make some of your requirements a little bit more flexible. You can't for example remove every version requirement from the hundreds of requirements and expect it to find a solution, I still had to very manually and iteratively loosen up the requirements. You might want to check how other large projects like apache-airflow
handle this? I think there are tools like pip compile that are supposed to help? (never had to look in to it myself).
We definitely have some old packages around for integrations that haven't been touched in years. Sometimes integration requirements get disabled when we raise our minimum Python version. Looks like we'll have to do so here too.
What makes it tricky to find the conflicting packages here is that everything is added at once. I wonder if it's possible you can break your integrations down in to logical sub groups and split your requirements in to those groups? Then at least you can test the issues in the groups and then once resolved see if you can install the groups together.
It's too bad that our lax handling of dependencies of our integrations is finally catching up on us. It means we'll need to pro-actively take care of it. Ccurrently we do it once an issue is raised that something doesn't work.
Python is a tricky language to manage such a large number of requirements. I wonder if you'll have to ultimately take some sort of vendoring approach so you can have different dependencies have different versions of their dependencies.
The requirements diff doesn't look too bad although I would hate to have to downgrade things (because it means we can't move forward!)
Yeah most of them look fine, but there's a few like open-meteo
where the downgrade looks very challenging :(.
We had the same problem with our CMS Plone which has lots of dependencies. With current pip main branch and this #10574 PR merged these issues are solved. Did you try it already?
I installed pip like so pip install git+https://github.com/pypa/pip.git#egg=pip
This is different, since they have dependency conflicts in the graph, rather than a dense graph post-resolve.
FWI we in apache-airflow don't handle this very well either, other than carefully (and somewhat blindly) altering our deps when we run into a backtracking issue.
In the past we used our constraints file to "solve" conflicts. That is similar to what is requested in https://github.com/pypa/pipenv/issues/4530 to work with the new resolver. Having that feature means we can move fast again with shipping security updates when needed without having to rush to ship a security fix and update X other packages that cause backtracking issues.
In the past we used our constraints file to "solve" conflicts. That is similar to what is requested in pypa/pipenv#4530 to work with the new resolver. Having that feature means we can move fast again with shipping security updates when needed without having to rush to ship a security fix and update X other packages that cause backtracking issues.
Yep - we have very sophisticated mechanism of both preparing and using constraints. In fact we are publishing a set of constraints for our users so that they can install airflow reliably. For example this is the only "official" way you can install 3.6 version of Airlfow 2.2.3 (from https://airflow.apache.org/docs/apache-airflow/stable/installation/installing-from-pypi.html)
pip install "apache-airflow[celery]==2.2.3" \
--constraint "https://raw.githubusercontent.com/apache/airflow/constraints-2.2.3/constraints-3.6.txt
The problem here is that it backtracked when we tried to upgrade the constraints. We have > 500 dependencies, so we do not upgrade constraints manually - we automated it. In our CI, the constraints will be automatically upgraded in the main build and whenever dependencies change. We are using --eager-upgrade
for that. After the --eager-upgrade
succeds, we run tests and only when tests pass we publish new constraints in "main" (which later are frozen when we release Airflow).
So in our case the backtracking happens (sometimes) when we attempt to generate new constraints with --eager-upgrade
(which excludes using existing constraints effectively).
BTW. It's pretty sophisticated mechanism with Airflow's >500 deps - I gave recently presentation on that where you can see most of the why's and how's if you are interested: https://www.youtube.com/watch?v=_SjMdQLP30s&t=2549s
Expected behavior
Done in less than 15 minutes.
wow, that's still long
pipenv's Pipfile.lock
could help. this should lock all dependencies, including transitive dependencies
at least this way, you can cache the resolution step
Expected behavior
Done in less than 15 minutes.
wow, that's still long
pipenv's
Pipfile.lock
could help. this should lock all dependencies, including transitive dependenciesat least this way, you can cache the resolution step
This only helps if you know a working set of dependencies to start with. The original set of requirements linked here didn't have a resolvable set of dependencies.
@balloob Are things better now, with the current release of pip?
We're still using the legacy resolver. We do have a GitHub Action in place to make sure we don't introduce new conflicts. However, we have no idea how we're going to handle upgrading components in the future once the legacy resolver is gone without being able to force a resolution (there was some recent discussion about this here can't find it right now). The atomicwrites
incident really scared us. With the modern resolver we would not have been able to publish a release until all dependencies (which are mostly volunteer-led) with conflicts had done a new release to resolve it.
As reported above, the resolving can be done in 15 minutes. So I guess this issue resolved 🥲
Description
The new resolver introduced in pip takes 12 hours to resolve Home Assistant, making it unusable for Home Assistant. Our current workaround is using the legacy resolver.
(Time measured on AMD Ryzen 7, 32GB memory)
The legacy resolver is going to be removed in #9631 making pip unusable for Home Assistant.
Home Assistant focuses on privacy and local control and is world’s largest open source home automation platform. In 2020 it was the 2nd most active Python project on GitHub (per State of the Octoverse 2020). We integrate over 1000 different APIs and each API is integrated via a Python package installed via pip (requirements.txt).
All our dependency versions are pinned, but the libraries that we use don’t pin their dependencies. This leads to long resolving time as the new resolver will download all the different potentially compatible versions to find the right one. Libraries don’t pin their dependencies because a library tries to be compatible with as many other projects as possible (we always make sure we don’t rely on HA specific API implementations).
I understand you don’t want to keep the legacy resolver around forever, but we would like to see that the new resolver is usable prior to it’s removal.
Expected behavior
Done in less than 15 minutes.
pip version
21.3.1
Python version
3.10
OS
Debian 11
How to Reproduce
Output
No response
Code of Conduct