Add filter to translation event listeners to avoid creating tasks (#110732)
This commit is contained in:
parent
6f74ea9186
commit
2cb0249f0a
2 changed files with 57 additions and 14 deletions
|
@ -5,7 +5,7 @@ import asyncio
|
||||||
from collections.abc import Iterable, Mapping
|
from collections.abc import Iterable, Mapping
|
||||||
import logging
|
import logging
|
||||||
import string
|
import string
|
||||||
from typing import Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
EVENT_COMPONENT_LOADED,
|
EVENT_COMPONENT_LOADED,
|
||||||
|
@ -205,6 +205,11 @@ class _TranslationCache:
|
||||||
self.cache: dict[str, dict[str, dict[str, dict[str, str]]]] = {}
|
self.cache: dict[str, dict[str, dict[str, dict[str, str]]]] = {}
|
||||||
self.lock = asyncio.Lock()
|
self.lock = asyncio.Lock()
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_is_loaded(self, language: str, components: set[str]) -> bool:
|
||||||
|
"""Return if the given components are loaded for the language."""
|
||||||
|
return components.issubset(self.loaded.get(language, set()))
|
||||||
|
|
||||||
async def async_load(
|
async def async_load(
|
||||||
self,
|
self,
|
||||||
language: str,
|
language: str,
|
||||||
|
@ -465,20 +470,41 @@ def async_setup(hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
Listeners load translations for every loaded component and after config change.
|
Listeners load translations for every loaded component and after config change.
|
||||||
"""
|
"""
|
||||||
|
cache = _TranslationCache(hass)
|
||||||
|
current_language = hass.config.language
|
||||||
|
hass.data[TRANSLATION_FLATTEN_CACHE] = cache
|
||||||
|
|
||||||
hass.data[TRANSLATION_FLATTEN_CACHE] = _TranslationCache(hass)
|
@callback
|
||||||
|
def _async_load_translations_filter(event: Event) -> bool:
|
||||||
|
"""Filter out unwanted events."""
|
||||||
|
nonlocal current_language
|
||||||
|
if (
|
||||||
|
new_language := event.data.get("language")
|
||||||
|
) and new_language != current_language:
|
||||||
|
current_language = new_language
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
async def load_translations(event: Event) -> None:
|
async def _async_load_translations(event: Event) -> None:
|
||||||
if "language" in event.data:
|
new_language = event.data["language"]
|
||||||
language = hass.config.language
|
_LOGGER.debug("Loading translations for language: %s", new_language)
|
||||||
_LOGGER.debug("Loading translations for language: %s", language)
|
await _async_load_state_translations_to_cache(hass, new_language, None)
|
||||||
await _async_load_state_translations_to_cache(hass, language, None)
|
|
||||||
|
|
||||||
async def load_translations_for_component(event: Event) -> None:
|
@callback
|
||||||
component = event.data.get("component")
|
def _async_load_translations_for_component_filter(event: Event) -> bool:
|
||||||
|
"""Filter out unwanted events."""
|
||||||
|
component: str | None = event.data.get("component")
|
||||||
# Platforms don't have their own translations, skip them
|
# Platforms don't have their own translations, skip them
|
||||||
if component is None or "." in str(component):
|
return bool(
|
||||||
return
|
component
|
||||||
|
and "." not in component
|
||||||
|
and not cache.async_is_loaded(hass.config.language, {component})
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _async_load_translations_for_component(event: Event) -> None:
|
||||||
|
component: str | None = event.data.get("component")
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
assert component is not None
|
||||||
language = hass.config.language
|
language = hass.config.language
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Loading translations for language: %s and component: %s",
|
"Loading translations for language: %s and component: %s",
|
||||||
|
@ -487,8 +513,16 @@ def async_setup(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
await _async_load_state_translations_to_cache(hass, language, component)
|
await _async_load_state_translations_to_cache(hass, language, component)
|
||||||
|
|
||||||
hass.bus.async_listen(EVENT_COMPONENT_LOADED, load_translations_for_component)
|
hass.bus.async_listen(
|
||||||
hass.bus.async_listen(EVENT_CORE_CONFIG_UPDATE, load_translations)
|
EVENT_COMPONENT_LOADED,
|
||||||
|
_async_load_translations_for_component,
|
||||||
|
event_filter=_async_load_translations_for_component_filter,
|
||||||
|
)
|
||||||
|
hass.bus.async_listen(
|
||||||
|
EVENT_CORE_CONFIG_UPDATE,
|
||||||
|
_async_load_translations,
|
||||||
|
event_filter=_async_load_translations_filter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
|
|
@ -602,12 +602,21 @@ async def test_setup(hass: HomeAssistant):
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock.assert_not_called()
|
mock.assert_not_called()
|
||||||
|
|
||||||
|
# Should not be called if the language is the current language
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.helpers.translation._async_load_state_translations_to_cache",
|
"homeassistant.helpers.translation._async_load_state_translations_to_cache",
|
||||||
) as mock:
|
) as mock:
|
||||||
hass.bus.async_fire(EVENT_CORE_CONFIG_UPDATE, {"language": "en"})
|
hass.bus.async_fire(EVENT_CORE_CONFIG_UPDATE, {"language": "en"})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock.assert_called_once_with(hass, hass.config.language, None)
|
mock.assert_not_called()
|
||||||
|
|
||||||
|
# Should be called if the language is different
|
||||||
|
with patch(
|
||||||
|
"homeassistant.helpers.translation._async_load_state_translations_to_cache",
|
||||||
|
) as mock:
|
||||||
|
hass.bus.async_fire(EVENT_CORE_CONFIG_UPDATE, {"language": "es"})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
mock.assert_called_once_with(hass, "es", None)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.helpers.translation._async_load_state_translations_to_cache",
|
"homeassistant.helpers.translation._async_load_state_translations_to_cache",
|
||||||
|
|
Loading…
Add table
Reference in a new issue