mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Adjust importlib helper to avoid leaking memory on re-raise (#115377)
This commit is contained in:
parent
6bd6adc4f5
commit
f0c8c2a684
@ -30,11 +30,9 @@ async def async_import_module(hass: HomeAssistant, name: str) -> ModuleType:
|
|||||||
if module := cache.get(name):
|
if module := cache.get(name):
|
||||||
return module
|
return module
|
||||||
|
|
||||||
failure_cache: dict[str, BaseException] = hass.data.setdefault(
|
failure_cache: dict[str, bool] = hass.data.setdefault(DATA_IMPORT_FAILURES, {})
|
||||||
DATA_IMPORT_FAILURES, {}
|
if name in failure_cache:
|
||||||
)
|
raise ModuleNotFoundError(f"{name} not found", name=name)
|
||||||
if exception := failure_cache.get(name):
|
|
||||||
raise exception
|
|
||||||
|
|
||||||
import_futures: dict[str, asyncio.Future[ModuleType]]
|
import_futures: dict[str, asyncio.Future[ModuleType]]
|
||||||
import_futures = hass.data.setdefault(DATA_IMPORT_FUTURES, {})
|
import_futures = hass.data.setdefault(DATA_IMPORT_FUTURES, {})
|
||||||
@ -51,7 +49,8 @@ async def async_import_module(hass: HomeAssistant, name: str) -> ModuleType:
|
|||||||
module = await hass.async_add_import_executor_job(_get_module, cache, name)
|
module = await hass.async_add_import_executor_job(_get_module, cache, name)
|
||||||
import_future.set_result(module)
|
import_future.set_result(module)
|
||||||
except BaseException as ex:
|
except BaseException as ex:
|
||||||
failure_cache[name] = ex
|
if isinstance(ex, ModuleNotFoundError):
|
||||||
|
failure_cache[name] = True
|
||||||
import_future.set_exception(ex)
|
import_future.set_exception(ex)
|
||||||
with suppress(BaseException):
|
with suppress(BaseException):
|
||||||
# Set the exception retrieved flag on the future since
|
# Set the exception retrieved flag on the future since
|
||||||
|
@ -41,16 +41,40 @@ async def test_async_import_module_failures(hass: HomeAssistant) -> None:
|
|||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
"homeassistant.helpers.importlib.importlib.import_module",
|
"homeassistant.helpers.importlib.importlib.import_module",
|
||||||
side_effect=ImportError,
|
side_effect=ValueError,
|
||||||
),
|
),
|
||||||
pytest.raises(ImportError),
|
pytest.raises(ValueError),
|
||||||
|
):
|
||||||
|
await importlib.async_import_module(hass, "test.module")
|
||||||
|
|
||||||
|
mock_module = MockModule()
|
||||||
|
# The failure should be not be cached
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.helpers.importlib.importlib.import_module",
|
||||||
|
return_value=mock_module,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
assert await importlib.async_import_module(hass, "test.module") is mock_module
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_import_module_failure_caches_module_not_found(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
) -> None:
|
||||||
|
"""Test importing a module caches ModuleNotFound."""
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.helpers.importlib.importlib.import_module",
|
||||||
|
side_effect=ModuleNotFoundError,
|
||||||
|
),
|
||||||
|
pytest.raises(ModuleNotFoundError),
|
||||||
):
|
):
|
||||||
await importlib.async_import_module(hass, "test.module")
|
await importlib.async_import_module(hass, "test.module")
|
||||||
|
|
||||||
mock_module = MockModule()
|
mock_module = MockModule()
|
||||||
# The failure should be cached
|
# The failure should be cached
|
||||||
with (
|
with (
|
||||||
pytest.raises(ImportError),
|
pytest.raises(ModuleNotFoundError),
|
||||||
patch(
|
patch(
|
||||||
"homeassistant.helpers.importlib.importlib.import_module",
|
"homeassistant.helpers.importlib.importlib.import_module",
|
||||||
return_value=mock_module,
|
return_value=mock_module,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user