mirror of
https://github.com/home-assistant/core.git
synced 2025-12-27 14:31:13 +00:00
Add support for preloading platforms in the loader (#112282)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
@@ -1094,27 +1094,36 @@ async def test_async_get_component_preloads_config_and_config_flow(
|
||||
assert "homeassistant.components.executor_import" not in sys.modules
|
||||
assert "custom_components.executor_import" not in sys.modules
|
||||
|
||||
platform_exists_calls = []
|
||||
|
||||
def mock_platforms_exists(platforms: list[str]) -> bool:
|
||||
platform_exists_calls.append(platforms)
|
||||
return platforms
|
||||
|
||||
with patch(
|
||||
"homeassistant.loader.importlib.import_module"
|
||||
) as mock_import, patch.object(
|
||||
executor_import_integration, "platform_exists", return_value=True
|
||||
) as mock_platform_exists:
|
||||
executor_import_integration, "platforms_exists", mock_platforms_exists
|
||||
):
|
||||
await executor_import_integration.async_get_component()
|
||||
|
||||
assert mock_platform_exists.call_count == 1
|
||||
assert mock_import.call_count == 3
|
||||
assert len(platform_exists_calls[0]) == len(loader.BASE_PRELOAD_PLATFORMS)
|
||||
assert mock_import.call_count == 2 + len(loader.BASE_PRELOAD_PLATFORMS)
|
||||
assert (
|
||||
mock_import.call_args_list[0][0][0]
|
||||
== "homeassistant.components.executor_import"
|
||||
)
|
||||
assert (
|
||||
mock_import.call_args_list[1][0][0]
|
||||
== "homeassistant.components.executor_import.config"
|
||||
)
|
||||
assert (
|
||||
mock_import.call_args_list[2][0][0]
|
||||
== "homeassistant.components.executor_import.config_flow"
|
||||
)
|
||||
checked_platforms = {
|
||||
mock_import.call_args_list[i][0][0]
|
||||
for i in range(1, len(mock_import.call_args_list))
|
||||
}
|
||||
assert checked_platforms == {
|
||||
"homeassistant.components.executor_import.config_flow",
|
||||
*(
|
||||
f"homeassistant.components.executor_import.{platform}"
|
||||
for platform in loader.BASE_PRELOAD_PLATFORMS
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
async def test_async_get_component_loads_loop_if_already_in_sys_modules(
|
||||
@@ -1134,8 +1143,8 @@ async def test_async_get_component_loads_loop_if_already_in_sys_modules(
|
||||
assert "test_package_loaded_executor.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()
|
||||
module_mock = MagicMock(__file__="__init__.py")
|
||||
config_flow_module_mock = MagicMock(__file__="config_flow.py")
|
||||
|
||||
def import_module(name: str) -> Any:
|
||||
if name == integration.pkg_path:
|
||||
@@ -1194,8 +1203,8 @@ async def test_async_get_component_concurrent_loads(
|
||||
assert "test_package_loaded_executor.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()
|
||||
module_mock = MagicMock(__file__="__init__.py")
|
||||
config_flow_module_mock = MagicMock(__file__="config_flow.py")
|
||||
imports = []
|
||||
start_event = threading.Event()
|
||||
import_event = asyncio.Event()
|
||||
@@ -1232,7 +1241,8 @@ async def test_async_get_component_concurrent_loads(
|
||||
assert comp1 is module_mock
|
||||
assert comp2 is module_mock
|
||||
|
||||
assert imports == [integration.pkg_path, config_flow_module_name]
|
||||
assert integration.pkg_path in imports
|
||||
assert config_flow_module_name in imports
|
||||
|
||||
|
||||
async def test_async_get_component_deadlock_fallback(
|
||||
@@ -1243,7 +1253,7 @@ async def test_async_get_component_deadlock_fallback(
|
||||
hass, "executor_import", True, import_executor=True
|
||||
)
|
||||
assert executor_import_integration.import_executor is True
|
||||
module_mock = MagicMock()
|
||||
module_mock = MagicMock(__file__="__init__.py")
|
||||
import_attempts = 0
|
||||
|
||||
def mock_import(module: str, *args: Any, **kwargs: Any) -> Any:
|
||||
@@ -1395,38 +1405,51 @@ async def test_async_get_platform_raises_after_import_failure(
|
||||
assert "loaded_executor=False" not in caplog.text
|
||||
|
||||
|
||||
async def test_platform_exists(
|
||||
async def test_platforms_exists(
|
||||
hass: HomeAssistant, enable_custom_integrations: None
|
||||
) -> None:
|
||||
"""Test platform_exists."""
|
||||
integration = await loader.async_get_integration(hass, "test_integration_platform")
|
||||
assert integration.domain == "test_integration_platform"
|
||||
"""Test platforms_exists."""
|
||||
original_os_listdir = os.listdir
|
||||
|
||||
# get_component never called, will return None
|
||||
assert integration.platform_exists("non_existing") is None
|
||||
paths: list[str] = []
|
||||
|
||||
component = integration.get_component()
|
||||
def mock_list_dir(path: str) -> list[str]:
|
||||
paths.append(path)
|
||||
return original_os_listdir(path)
|
||||
|
||||
with patch("homeassistant.loader.os.listdir", mock_list_dir):
|
||||
integration = await loader.async_get_integration(
|
||||
hass, "test_integration_platform"
|
||||
)
|
||||
assert integration.domain == "test_integration_platform"
|
||||
|
||||
# Verify the files cache is primed
|
||||
assert integration.file_path in paths
|
||||
|
||||
# component is loaded, should now return False
|
||||
with patch("homeassistant.loader.os.listdir", wraps=os.listdir) as mock_exists:
|
||||
component = integration.get_component()
|
||||
assert component.DOMAIN == "test_integration_platform"
|
||||
|
||||
# component is loaded, should now return False
|
||||
with patch(
|
||||
"homeassistant.loader.os.path.exists", wraps=os.path.exists
|
||||
) as mock_exists:
|
||||
assert integration.platform_exists("non_existing") is False
|
||||
|
||||
# We should check if the file exists
|
||||
assert mock_exists.call_count == 2
|
||||
# The files cache should be primed when
|
||||
# the integration is resolved
|
||||
assert mock_exists.call_count == 0
|
||||
|
||||
# component is loaded, should now return False
|
||||
with patch(
|
||||
"homeassistant.loader.os.path.exists", wraps=os.path.exists
|
||||
) as mock_exists:
|
||||
assert integration.platform_exists("non_existing") is False
|
||||
with patch("homeassistant.loader.os.listdir", wraps=os.listdir) as mock_exists:
|
||||
assert integration.platforms_exists(("non_existing",)) == []
|
||||
|
||||
# We should remember which files exist
|
||||
assert mock_exists.call_count == 0
|
||||
|
||||
# component is loaded, should now return False
|
||||
with patch("homeassistant.loader.os.listdir", wraps=os.listdir) as mock_exists:
|
||||
assert integration.platforms_exists(("non_existing",)) == []
|
||||
|
||||
# We should remember the file does not exist
|
||||
assert mock_exists.call_count == 0
|
||||
|
||||
assert integration.platform_exists("group") is True
|
||||
assert integration.platforms_exists(["group"]) == ["group"]
|
||||
|
||||
platform = await integration.async_get_platform("group")
|
||||
assert platform.MAGIC == 1
|
||||
@@ -1434,7 +1457,7 @@ async def test_platform_exists(
|
||||
platform = integration.get_platform("group")
|
||||
assert platform.MAGIC == 1
|
||||
|
||||
assert integration.platform_exists("group") is True
|
||||
assert integration.platforms_exists(["group"]) == ["group"]
|
||||
|
||||
|
||||
async def test_async_get_platforms_loads_loop_if_already_in_sys_modules(
|
||||
|
||||
Reference in New Issue
Block a user