mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 07:07:28 +00:00
Fix async_get_component loading in the executor when the module is already loaded (#112153)
This commit is contained in:
parent
bef8376f83
commit
f4b2c9b569
@ -847,8 +847,9 @@ class Integration:
|
|||||||
domain = self.domain
|
domain = self.domain
|
||||||
# Some integrations fail on import because they call functions incorrectly.
|
# Some integrations fail on import because they call functions incorrectly.
|
||||||
# So we do it before validating config to catch these errors.
|
# So we do it before validating config to catch these errors.
|
||||||
load_executor = (
|
load_executor = self.import_executor and (
|
||||||
self.import_executor and f"{self.pkg_path}.{domain}" not in sys.modules
|
self.pkg_path not in sys.modules
|
||||||
|
or (self.config_flow and f"{self.pkg_path}.config_flow" not in sys.modules)
|
||||||
)
|
)
|
||||||
if load_executor:
|
if load_executor:
|
||||||
try:
|
try:
|
||||||
|
@ -1073,6 +1073,66 @@ async def test_async_get_component_preloads_config_and_config_flow(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_get_component_loads_loop_if_already_in_sys_modules(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
enable_custom_integrations: None,
|
||||||
|
) -> None:
|
||||||
|
"""Verify async_get_component does not create an executor job if the module is already in sys.modules."""
|
||||||
|
integration = await loader.async_get_integration(
|
||||||
|
hass, "test_package_loaded_executor"
|
||||||
|
)
|
||||||
|
assert integration.pkg_path == "custom_components.test_package_loaded_executor"
|
||||||
|
assert integration.import_executor is True
|
||||||
|
assert integration.config_flow is True
|
||||||
|
|
||||||
|
assert "executor_import" not in hass.config.components
|
||||||
|
assert "executor_import.config_flow" not in hass.config.components
|
||||||
|
|
||||||
|
config_flow_module_name = f"{integration.pkg_path}.config_flow"
|
||||||
|
module_mock = MagicMock()
|
||||||
|
config_flow_module_mock = MagicMock()
|
||||||
|
|
||||||
|
def import_module(name: str) -> Any:
|
||||||
|
if name == integration.pkg_path:
|
||||||
|
return module_mock
|
||||||
|
if name == config_flow_module_name:
|
||||||
|
return config_flow_module_mock
|
||||||
|
raise ImportError
|
||||||
|
|
||||||
|
modules_without_config_flow = {
|
||||||
|
k: v for k, v in sys.modules.items() if k != config_flow_module_name
|
||||||
|
}
|
||||||
|
with patch.dict(
|
||||||
|
"sys.modules",
|
||||||
|
{**modules_without_config_flow, integration.pkg_path: module_mock},
|
||||||
|
clear=True,
|
||||||
|
), patch("homeassistant.loader.importlib.import_module", import_module):
|
||||||
|
module = await integration.async_get_component()
|
||||||
|
|
||||||
|
# The config flow is missing so we should load
|
||||||
|
# in the executor
|
||||||
|
assert "loaded_executor=True" in caplog.text
|
||||||
|
assert "loaded_executor=False" not in caplog.text
|
||||||
|
assert module is module_mock
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
with patch.dict(
|
||||||
|
"sys.modules",
|
||||||
|
{
|
||||||
|
integration.pkg_path: module_mock,
|
||||||
|
config_flow_module_name: config_flow_module_mock,
|
||||||
|
},
|
||||||
|
), patch("homeassistant.loader.importlib.import_module", import_module):
|
||||||
|
module = await integration.async_get_component()
|
||||||
|
|
||||||
|
# Everything is there so we should load in the event loop
|
||||||
|
# since it will all be cached
|
||||||
|
assert "loaded_executor=False" in caplog.text
|
||||||
|
assert "loaded_executor=True" not in caplog.text
|
||||||
|
assert module is module_mock
|
||||||
|
|
||||||
|
|
||||||
async def test_async_get_component_deadlock_fallback(
|
async def test_async_get_component_deadlock_fallback(
|
||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user