Add missing translations for LG webOS TV and fix names (#136438)

This commit is contained in:
Shay Levy 2025-01-24 15:13:10 +02:00 committed by GitHub
parent 5d353a9833
commit 47efb68780
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 92 additions and 75 deletions

View File

@ -1,14 +1,12 @@
"""Support for LG webOS Smart TV."""
"""The LG webOS TV integration."""
from __future__ import annotations
from contextlib import suppress
import logging
from aiowebostv import WebOsClient, WebOsTvPairError
from homeassistant.components import notify as hass_notify
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_CLIENT_SECRET,
CONF_HOST,
@ -29,17 +27,13 @@ from .const import (
PLATFORMS,
WEBOSTV_EXCEPTIONS,
)
from .helpers import WebOsTvConfigEntry, update_client_key
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
_LOGGER = logging.getLogger(__name__)
type WebOsTvConfigEntry = ConfigEntry[WebOsClient]
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the LG WebOS TV platform."""
"""Set up the LG webOS TV platform."""
hass.data.setdefault(DOMAIN, {DATA_HASS_CONFIG: config})
return True
@ -62,7 +56,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: WebOsTvConfigEntry) -> b
# If pairing request accepted there will be no error
# Update the stored key without triggering reauth
update_client_key(hass, entry, client)
update_client_key(hass, entry)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
@ -99,19 +93,6 @@ async def async_update_options(hass: HomeAssistant, entry: WebOsTvConfigEntry) -
await hass.config_entries.async_reload(entry.entry_id)
def update_client_key(
hass: HomeAssistant, entry: ConfigEntry, client: WebOsClient
) -> None:
"""Check and update stored client key if key has changed."""
host = entry.data[CONF_HOST]
key = entry.data[CONF_CLIENT_SECRET]
if client.client_key != key:
_LOGGER.debug("Updating client key for host %s", host)
data = {CONF_HOST: host, CONF_CLIENT_SECRET: client.client_key}
hass.config_entries.async_update_entry(entry, data=data)
async def async_unload_entry(hass: HomeAssistant, entry: WebOsTvConfigEntry) -> bool:
"""Unload a config entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):

View File

@ -1,4 +1,4 @@
"""Config flow to configure webostv component."""
"""Config flow for LG webOS TV integration."""
from __future__ import annotations
@ -35,7 +35,7 @@ DATA_SCHEMA = vol.Schema(
async def async_control_connect(
hass: HomeAssistant, host: str, key: str | None
) -> WebOsClient:
"""Create LG WebOS client and connect to the TV."""
"""Create LG webOS client and connect to the TV."""
client = WebOsClient(
host,
key,
@ -48,7 +48,7 @@ async def async_control_connect(
class FlowHandler(ConfigFlow, domain=DOMAIN):
"""WebosTV configuration flow."""
"""LG webOS TV configuration flow."""
VERSION = 1

View File

@ -1,4 +1,4 @@
"""Constants used for LG webOS Smart TV."""
"""Constants for the LG webOS TV integration."""
import asyncio

View File

@ -1,4 +1,4 @@
"""Provides device automations for control of LG webOS Smart TV."""
"""Provides device automations for control of LG webOS TV."""
from __future__ import annotations

View File

@ -1,4 +1,4 @@
"""Diagnostics support for LG webOS Smart TV."""
"""Diagnostics support for LG webOS TV."""
from __future__ import annotations

View File

@ -1,17 +1,24 @@
"""Helper functions for webOS Smart TV."""
"""Helper functions for LG webOS TV."""
from __future__ import annotations
import logging
from aiowebostv import WebOsClient
from homeassistant.config_entries import ConfigEntryState
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.const import CONF_CLIENT_SECRET, CONF_HOST
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.device_registry import DeviceEntry
from . import WebOsTvConfigEntry
from .const import DOMAIN, LIVE_TV_APP_ID
_LOGGER = logging.getLogger(__name__)
type WebOsTvConfigEntry = ConfigEntry[WebOsClient]
@callback
def async_get_device_entry_by_device_id(
@ -32,7 +39,7 @@ def async_get_device_entry_by_device_id(
def async_get_device_id_from_entity_id(hass: HomeAssistant, entity_id: str) -> str:
"""Get device ID from an entity ID.
Raises ValueError if entity or device ID is invalid.
Raises HomeAssistantError if entity or device ID is invalid.
"""
ent_reg = er.async_get(hass)
entity_entry = ent_reg.async_get(entity_id)
@ -42,7 +49,11 @@ def async_get_device_id_from_entity_id(hass: HomeAssistant, entity_id: str) -> s
or entity_entry.device_id is None
or entity_entry.platform != DOMAIN
):
raise ValueError(f"Entity {entity_id} is not a valid {DOMAIN} entity.")
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="invalid_entity_id",
translation_placeholders={"entity_id": entity_id},
)
return entity_entry.device_id
@ -91,3 +102,15 @@ def get_sources(client: WebOsClient) -> list[str]:
# Preserve order when filtering duplicates
return list(dict.fromkeys(sources))
def update_client_key(hass: HomeAssistant, entry: WebOsTvConfigEntry) -> None:
"""Check and update stored client key if key has changed."""
client: WebOsClient = entry.runtime_data
host = entry.data[CONF_HOST]
key = entry.data[CONF_CLIENT_SECRET]
if client.client_key != key:
_LOGGER.debug("Updating client key for host %s", host)
data = {CONF_HOST: host, CONF_CLIENT_SECRET: client.client_key}
hass.config_entries.async_update_entry(entry, data=data)

View File

@ -1,4 +1,4 @@
"""Support for interface with an LG webOS Smart TV."""
"""Support for interface with an LG webOS TV."""
from __future__ import annotations
@ -33,7 +33,6 @@ from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.trigger import PluggableAction
from homeassistant.helpers.typing import VolDictType
from . import WebOsTvConfigEntry, update_client_key
from .const import (
ATTR_BUTTON,
ATTR_PAYLOAD,
@ -46,6 +45,7 @@ from .const import (
SERVICE_SELECT_SOUND_OUTPUT,
WEBOSTV_EXCEPTIONS,
)
from .helpers import WebOsTvConfigEntry, update_client_key
from .triggers.turn_on import async_get_turn_on_trigger
_LOGGER = logging.getLogger(__name__)
@ -89,7 +89,7 @@ async def async_setup_entry(
entry: WebOsTvConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the LG webOS Smart TV platform."""
"""Set up the LG webOS TV platform."""
platform = entity_platform.async_get_current_platform()
for service_name, schema, method in SERVICES:
@ -132,7 +132,7 @@ def cmd[_T: LgWebOSMediaPlayerEntity, **_P](
class LgWebOSMediaPlayerEntity(RestoreEntity, MediaPlayerEntity):
"""Representation of a LG webOS Smart TV."""
"""Representation of a LG webOS TV."""
_attr_device_class = MediaPlayerDeviceClass.TV
_attr_has_entity_name = True
@ -335,7 +335,7 @@ class LgWebOSMediaPlayerEntity(RestoreEntity, MediaPlayerEntity):
except WebOsTvPairError:
self._entry.async_start_reauth(self.hass)
else:
update_client_key(self.hass, self._entry, self._client)
update_client_key(self.hass, self._entry)
@property
def supported_features(self) -> MediaPlayerEntityFeature:
@ -392,10 +392,14 @@ class LgWebOSMediaPlayerEntity(RestoreEntity, MediaPlayerEntity):
async def async_select_source(self, source: str) -> None:
"""Select input source."""
if (source_dict := self._source_list.get(source)) is None:
_LOGGER.warning(
"Source %s not found for %s", source, self._friendly_name_internal()
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="source_not_found",
translation_placeholders={
"source": source,
"name": str(self._friendly_name_internal()),
},
)
return
if source_dict.get("title"):
await self._client.launch_app(source_dict["id"])
elif source_dict.get("label"):

View File

@ -1,4 +1,4 @@
"""Support for LG WebOS TV notification service."""
"""Support for LG webOS TV notification service."""
from __future__ import annotations
@ -37,7 +37,7 @@ async def async_get_service(
class LgWebOSNotificationService(BaseNotificationService):
"""Implement the notification service for LG WebOS TV."""
"""Implement the notification service for LG webOS TV."""
def __init__(self, entry: WebOsTvConfigEntry) -> None:
"""Initialize the service."""

View File

@ -12,7 +12,7 @@
}
},
"pairing": {
"title": "webOS TV Pairing",
"title": "LG webOS TV Pairing",
"description": "Select **Submit** and accept the pairing request on your TV.\n\n![Image](/static/images/config_webos.png)"
},
"reauth_confirm": {
@ -43,7 +43,7 @@
"options": {
"step": {
"init": {
"title": "Options for webOS Smart TV",
"title": "Options for LG webOS TV",
"description": "Select enabled sources",
"data": {
"sources": "Sources list"
@ -129,6 +129,15 @@
},
"unhandled_trigger_type": {
"message": "Unhandled trigger type: {trigger_type}"
},
"unknown_trigger_platform": {
"message": "Unknown trigger platform: {platform}"
},
"invalid_entity_id": {
"message": "Entity {entity_id} is not a valid webostv entity."
},
"source_not_found": {
"message": "Source {source} not found in the sources list for {name}."
}
}
}

View File

@ -1,4 +1,4 @@
"""webOS Smart TV trigger dispatcher."""
"""LG webOS TV trigger dispatcher."""
from __future__ import annotations
@ -6,6 +6,7 @@ from typing import cast
from homeassistant.const import CONF_PLATFORM
from homeassistant.core import CALLBACK_TYPE, HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.trigger import (
TriggerActionType,
TriggerInfo,
@ -13,6 +14,7 @@ from homeassistant.helpers.trigger import (
)
from homeassistant.helpers.typing import ConfigType
from .const import DOMAIN
from .triggers import turn_on
TRIGGERS = {
@ -24,8 +26,10 @@ def _get_trigger_platform(config: ConfigType) -> TriggerProtocol:
"""Return trigger platform."""
platform_split = config[CONF_PLATFORM].split(".", maxsplit=1)
if len(platform_split) < 2 or platform_split[1] not in TRIGGERS:
raise ValueError(
f"Unknown webOS Smart TV trigger platform {config[CONF_PLATFORM]}"
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="unknown_trigger_platform",
translation_placeholders={"platform": config[CONF_PLATFORM]},
)
return cast(TriggerProtocol, TRIGGERS[platform_split[1]])

View File

@ -1 +1 @@
"""webOS Smart TV triggers."""
"""LG webOS TV triggers."""

View File

@ -1,4 +1,4 @@
"""webOS Smart TV device turn on trigger."""
"""LG webOS TV device turn on trigger."""
from __future__ import annotations

View File

@ -1,4 +1,4 @@
"""Tests for the WebOS TV integration."""
"""Tests for the LG webOS TV integration."""
from homeassistant.components.webostv.const import DOMAIN
from homeassistant.const import CONF_CLIENT_SECRET, CONF_HOST

View File

@ -1,4 +1,4 @@
"""Common fixtures and objects for the LG webOS integration tests."""
"""Common fixtures and objects for the LG webOS TV integration tests."""
from collections.abc import Generator
from unittest.mock import AsyncMock, Mock, patch

View File

@ -1,4 +1,4 @@
"""Constants for LG webOS Smart TV tests."""
"""Constants for LG webOS TV tests."""
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
from homeassistant.components.webostv.const import LIVE_TV_APP_ID

View File

@ -1,4 +1,4 @@
"""Test the WebOS Tv config flow."""
"""Test the LG webOS TV config flow."""
from aiowebostv import WebOsTvPairError
import pytest

View File

@ -1,4 +1,4 @@
"""The tests for WebOS TV device triggers."""
"""The tests for LG webOS TV device triggers."""
import pytest
@ -140,7 +140,6 @@ async def test_invalid_entry_raises(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
client,
caplog: pytest.LogCaptureFixture,
domain: str,
entry_state: ConfigEntryState,
) -> None:

View File

@ -1,4 +1,4 @@
"""Tests for the diagnostics data provided by LG webOS Smart TV."""
"""Tests for the diagnostics data provided by LG webOS TV."""
from syrupy.assertion import SnapshotAssertion
from syrupy.filters import props

View File

@ -1,4 +1,4 @@
"""The tests for the LG webOS media player platform."""
"""The tests for the LG webOS TV media player platform."""
from datetime import timedelta
from http import HTTPStatus
@ -165,7 +165,7 @@ async def test_media_next_previous_track(
async def test_select_source_with_empty_source_list(
hass: HomeAssistant, client, caplog: pytest.LogCaptureFixture
hass: HomeAssistant, client
) -> None:
"""Ensure we don't call client methods when we don't have sources."""
await setup_webostv(hass)
@ -175,11 +175,14 @@ async def test_select_source_with_empty_source_list(
ATTR_ENTITY_ID: ENTITY_ID,
ATTR_INPUT_SOURCE: "nonexistent",
}
await hass.services.async_call(MP_DOMAIN, SERVICE_SELECT_SOURCE, data, True)
with pytest.raises(
HomeAssistantError,
match=f"Source nonexistent not found in the sources list for {TV_NAME}",
):
await hass.services.async_call(MP_DOMAIN, SERVICE_SELECT_SOURCE, data, True)
client.launch_app.assert_not_called()
client.set_input.assert_not_called()
assert f"Source nonexistent not found for {TV_NAME}" in caplog.text
async def test_select_app_source(hass: HomeAssistant, client) -> None:

View File

@ -1,4 +1,4 @@
"""The tests for the WebOS TV notify platform."""
"""The tests for the LG webOS TV notify platform."""
from unittest.mock import call

View File

@ -1,4 +1,4 @@
"""The tests for WebOS TV automation triggers."""
"""The tests for LG webOS TV automation triggers."""
from unittest.mock import patch
@ -118,10 +118,10 @@ async def test_webostv_turn_on_trigger_entity_id(
assert service_calls[1].data["id"] == 0
async def test_wrong_trigger_platform_type(
async def test_unknown_trigger_platform_type(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, client
) -> None:
"""Test wrong trigger platform type."""
"""Test unknown trigger platform type."""
await setup_webostv(hass)
await async_setup_component(
@ -131,7 +131,7 @@ async def test_wrong_trigger_platform_type(
automation.DOMAIN: [
{
"trigger": {
"platform": "webostv.wrong_type",
"platform": "webostv.unknown",
"entity_id": ENTITY_ID,
},
"action": {
@ -146,10 +146,7 @@ async def test_wrong_trigger_platform_type(
},
)
assert (
"ValueError: Unknown webOS Smart TV trigger platform webostv.wrong_type"
in caplog.text
)
assert "Unknown trigger platform: webostv.unknown" in caplog.text
async def test_trigger_invalid_entity_id(
@ -185,7 +182,4 @@ async def test_trigger_invalid_entity_id(
},
)
assert (
f"ValueError: Entity {invalid_entity} is not a valid webostv entity"
in caplog.text
)
assert f"Entity {invalid_entity} is not a valid {DOMAIN} entity" in caplog.text