mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Avoid falling back to event loop import on ModuleNotFound (#115404)
This commit is contained in:
parent
28bdbec14e
commit
fb5fc136e8
@ -976,6 +976,8 @@ class Integration:
|
|||||||
comp = await self.hass.async_add_import_executor_job(
|
comp = await self.hass.async_add_import_executor_job(
|
||||||
self._get_component, True
|
self._get_component, True
|
||||||
)
|
)
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
raise
|
||||||
except ImportError as ex:
|
except ImportError as ex:
|
||||||
load_executor = False
|
load_executor = False
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
@ -1115,6 +1117,8 @@ class Integration:
|
|||||||
self._load_platforms, platform_names
|
self._load_platforms, platform_names
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
raise
|
||||||
except ImportError as ex:
|
except ImportError as ex:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Failed to import %s platforms %s in executor",
|
"Failed to import %s platforms %s in executor",
|
||||||
|
@ -1471,6 +1471,50 @@ async def test_async_get_component_deadlock_fallback(
|
|||||||
assert module is module_mock
|
assert module is module_mock
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_get_component_deadlock_fallback_module_not_found(
|
||||||
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
|
"""Verify async_get_component fallback behavior.
|
||||||
|
|
||||||
|
Ensure that fallback is not triggered on ModuleNotFoundError.
|
||||||
|
"""
|
||||||
|
executor_import_integration = _get_test_integration(
|
||||||
|
hass, "executor_import", True, import_executor=True
|
||||||
|
)
|
||||||
|
assert executor_import_integration.import_executor is True
|
||||||
|
module_mock = MagicMock(__file__="__init__.py")
|
||||||
|
import_attempts = 0
|
||||||
|
|
||||||
|
def mock_import(module: str, *args: Any, **kwargs: Any) -> Any:
|
||||||
|
nonlocal import_attempts
|
||||||
|
if module == "homeassistant.components.executor_import":
|
||||||
|
import_attempts += 1
|
||||||
|
|
||||||
|
if import_attempts == 1:
|
||||||
|
raise ModuleNotFoundError(
|
||||||
|
"homeassistant.components.executor_import not found",
|
||||||
|
name="homeassistant.components.executor_import",
|
||||||
|
)
|
||||||
|
|
||||||
|
return module_mock
|
||||||
|
|
||||||
|
assert "homeassistant.components.executor_import" not in sys.modules
|
||||||
|
assert "custom_components.executor_import" not in sys.modules
|
||||||
|
with (
|
||||||
|
patch("homeassistant.loader.importlib.import_module", mock_import),
|
||||||
|
pytest.raises(
|
||||||
|
ModuleNotFoundError, match="homeassistant.components.executor_import"
|
||||||
|
),
|
||||||
|
):
|
||||||
|
await executor_import_integration.async_get_component()
|
||||||
|
|
||||||
|
# We should not have tried to fall back to the event loop import
|
||||||
|
assert "loaded_executor=False" not in caplog.text
|
||||||
|
assert "homeassistant.components.executor_import" not in sys.modules
|
||||||
|
assert "custom_components.executor_import" not in sys.modules
|
||||||
|
assert import_attempts == 1
|
||||||
|
|
||||||
|
|
||||||
async def test_async_get_component_raises_after_import_failure(
|
async def test_async_get_component_raises_after_import_failure(
|
||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -1551,6 +1595,52 @@ async def test_async_get_platform_deadlock_fallback(
|
|||||||
assert module is module_mock
|
assert module is module_mock
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_get_platform_deadlock_fallback_module_not_found(
|
||||||
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
|
"""Verify async_get_platform fallback behavior.
|
||||||
|
|
||||||
|
Ensure that fallback is not triggered on ModuleNotFoundError.
|
||||||
|
"""
|
||||||
|
executor_import_integration = _get_test_integration(
|
||||||
|
hass, "executor_import", True, import_executor=True
|
||||||
|
)
|
||||||
|
assert executor_import_integration.import_executor is True
|
||||||
|
module_mock = MagicMock()
|
||||||
|
import_attempts = 0
|
||||||
|
|
||||||
|
def mock_import(module: str, *args: Any, **kwargs: Any) -> Any:
|
||||||
|
nonlocal import_attempts
|
||||||
|
if module == "homeassistant.components.executor_import.config_flow":
|
||||||
|
import_attempts += 1
|
||||||
|
|
||||||
|
if import_attempts == 1:
|
||||||
|
raise ModuleNotFoundError(
|
||||||
|
"Not found homeassistant.components.executor_import.config_flow",
|
||||||
|
name="homeassistant.components.executor_import.config_flow",
|
||||||
|
)
|
||||||
|
|
||||||
|
return module_mock
|
||||||
|
|
||||||
|
assert "homeassistant.components.executor_import" not in sys.modules
|
||||||
|
assert "custom_components.executor_import" not in sys.modules
|
||||||
|
with (
|
||||||
|
patch("homeassistant.loader.importlib.import_module", mock_import),
|
||||||
|
pytest.raises(
|
||||||
|
ModuleNotFoundError,
|
||||||
|
match="homeassistant.components.executor_import.config_flow",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
await executor_import_integration.async_get_platform("config_flow")
|
||||||
|
|
||||||
|
# We should not have tried to fall back to the event loop import
|
||||||
|
assert "executor=['config_flow']" in caplog.text
|
||||||
|
assert "loop=['config_flow']" not in caplog.text
|
||||||
|
assert "homeassistant.components.executor_import" not in sys.modules
|
||||||
|
assert "custom_components.executor_import" not in sys.modules
|
||||||
|
assert import_attempts == 1
|
||||||
|
|
||||||
|
|
||||||
async def test_async_get_platform_raises_after_import_failure(
|
async def test_async_get_platform_raises_after_import_failure(
|
||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user