From 17ba96ffdb241b8a458c5f6b89c9fafaf7f7f796 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Feb 2024 20:30:07 -0600 Subject: [PATCH] Avoid creating tasks to install dependent requirements (#111048) --- homeassistant/requirements.py | 37 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/homeassistant/requirements.py b/homeassistant/requirements.py index e2713bad16f..f1add1ff3f8 100644 --- a/homeassistant/requirements.py +++ b/homeassistant/requirements.py @@ -226,21 +226,28 @@ class RequirementsManager: if not deps_to_check: return - results = await asyncio.gather( - *( - self.async_get_integration_with_requirements(dep, done) - for dep in deps_to_check - ), - return_exceptions=True, - ) - for result in results: - if not isinstance(result, BaseException): - continue - if not isinstance(result, IntegrationNotFound) or not ( - not integration.is_built_in - and result.domain in integration.after_dependencies - ): - raise result + exceptions: list[Exception] = [] + # We don't create tasks here since everything waits for the pip lock + # anyways and we want to make sure we don't start a bunch of tasks + # that will just wait for the lock. + for dep in deps_to_check: + # We want all the async_get_integration_with_requirements calls to + # happen even if one fails. So we catch the exception and store it + # to raise the first one after all are done to behave like asyncio + # gather. + try: + await self.async_get_integration_with_requirements(dep, done) + except IntegrationNotFound as ex: + if ( + integration.is_built_in + or ex.domain not in integration.after_dependencies + ): + exceptions.append(ex) + except Exception as ex: # pylint: disable=broad-except + exceptions.insert(0, ex) + + if exceptions: + raise exceptions[0] async def async_process_requirements( self, name: str, requirements: list[str]