Get ServiceValidationError message from translation cache only (#113704)

* Get ServiceValidationError message from translation cache only

* Remove message for NotValidPresetModeError
This commit is contained in:
Jan Bouwhuis 2024-03-18 14:42:21 +01:00 committed by GitHub
parent ec7aecef84
commit 3dc8df2403
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 16 additions and 43 deletions

View file

@ -150,7 +150,6 @@ class BSBLANClimate(
await self.async_set_data(preset_mode=preset_mode) await self.async_set_data(preset_mode=preset_mode)
else: else:
raise ServiceValidationError( raise ServiceValidationError(
"Can't set preset mode when hvac mode is not auto",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="set_preset_mode_error", translation_key="set_preset_mode_error",
translation_placeholders={"preset_mode": preset_mode}, translation_placeholders={"preset_mode": preset_mode},

View file

@ -95,7 +95,6 @@ def __get_coordinator(
if not entry: if not entry:
raise ServiceValidationError( raise ServiceValidationError(
f"Invalid config entry: {entry_id}",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="invalid_config_entry", translation_key="invalid_config_entry",
translation_placeholders={ translation_placeholders={
@ -104,7 +103,6 @@ def __get_coordinator(
) )
if entry.state != ConfigEntryState.LOADED: if entry.state != ConfigEntryState.LOADED:
raise ServiceValidationError( raise ServiceValidationError(
f"{entry.title} is not loaded",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="unloaded_config_entry", translation_key="unloaded_config_entry",
translation_placeholders={ translation_placeholders={

View file

@ -337,7 +337,6 @@ class EcovacsVacuum(
params = {} params = {}
elif isinstance(params, list): elif isinstance(params, list):
raise ServiceValidationError( raise ServiceValidationError(
"Params must be a dict!",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="vacuum_send_command_params_dict", translation_key="vacuum_send_command_params_dict",
) )
@ -345,7 +344,6 @@ class EcovacsVacuum(
if command in ["spot_area", "custom_area"]: if command in ["spot_area", "custom_area"]:
if params is None: if params is None:
raise ServiceValidationError( raise ServiceValidationError(
f"Params are required for {command}!",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="vacuum_send_command_params_required", translation_key="vacuum_send_command_params_required",
translation_placeholders={"command": command}, translation_placeholders={"command": command},
@ -354,7 +352,6 @@ class EcovacsVacuum(
info = self._device.device_info info = self._device.device_info
name = info.get("nick", info["name"]) name = info.get("nick", info["name"])
raise ServiceValidationError( raise ServiceValidationError(
f"Vacuum {name} does not support area capability!",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="vacuum_send_command_area_not_supported", translation_key="vacuum_send_command_area_not_supported",
translation_placeholders={"name": name}, translation_placeholders={"name": name},

View file

@ -62,7 +62,6 @@ def __get_date(date_input: str | None) -> date | datetime:
return value return value
raise ServiceValidationError( raise ServiceValidationError(
"Invalid datetime provided.",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="invalid_date", translation_key="invalid_date",
translation_placeholders={ translation_placeholders={
@ -93,7 +92,6 @@ def __get_coordinator(
if not entry: if not entry:
raise ServiceValidationError( raise ServiceValidationError(
f"Invalid config entry: {entry_id}",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="invalid_config_entry", translation_key="invalid_config_entry",
translation_placeholders={ translation_placeholders={
@ -102,7 +100,6 @@ def __get_coordinator(
) )
if entry.state != ConfigEntryState.LOADED: if entry.state != ConfigEntryState.LOADED:
raise ServiceValidationError( raise ServiceValidationError(
f"{entry.title} is not loaded",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="unloaded_config_entry", translation_key="unloaded_config_entry",
translation_placeholders={ translation_placeholders={

View file

@ -297,8 +297,6 @@ class FanEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
if not preset_modes or preset_mode not in preset_modes: if not preset_modes or preset_mode not in preset_modes:
preset_modes_str: str = ", ".join(preset_modes or []) preset_modes_str: str = ", ".join(preset_modes or [])
raise NotValidPresetModeError( raise NotValidPresetModeError(
f"The preset_mode {preset_mode} is not a valid preset_mode:"
f" {preset_modes}",
translation_placeholders={ translation_placeholders={
"preset_mode": preset_mode, "preset_mode": preset_mode,
"preset_modes": preset_modes_str, "preset_modes": preset_modes_str,

View file

@ -282,7 +282,6 @@ async def async_setup_platform(
scene = platform.entities.get(entity_id) scene = platform.entities.get(entity_id)
if scene is None: if scene is None:
raise ServiceValidationError( raise ServiceValidationError(
f"{entity_id} is not a valid scene entity_id",
translation_domain=SCENE_DOMAIN, translation_domain=SCENE_DOMAIN,
translation_key="entity_not_scene", translation_key="entity_not_scene",
translation_placeholders={ translation_placeholders={
@ -292,7 +291,6 @@ async def async_setup_platform(
assert isinstance(scene, HomeAssistantScene) assert isinstance(scene, HomeAssistantScene)
if not scene.from_service: if not scene.from_service:
raise ServiceValidationError( raise ServiceValidationError(
f"The scene {entity_id} is not created with service `scene.create`",
translation_domain=SCENE_DOMAIN, translation_domain=SCENE_DOMAIN,
translation_key="entity_not_dynamically_created", translation_key="entity_not_dynamically_created",
translation_placeholders={ translation_placeholders={

View file

@ -156,7 +156,6 @@ class LockEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
if TYPE_CHECKING: if TYPE_CHECKING:
assert self.code_format assert self.code_format
raise ServiceValidationError( raise ServiceValidationError(
f"The code for {self.entity_id} doesn't match pattern {self.code_format}",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="add_default_code", translation_key="add_default_code",
translation_placeholders={ translation_placeholders={

View file

@ -331,8 +331,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
except vol.Invalid as err: except vol.Invalid as err:
err_str = str(err) err_str = str(err)
raise ServiceValidationError( raise ServiceValidationError(
f"Unable to publish: topic template '{msg_topic_template}' produced an "
f"invalid topic '{rendered_topic}' after rendering ({err_str})",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="invalid_publish_topic", translation_key="invalid_publish_topic",
translation_placeholders={ translation_placeholders={
@ -405,7 +403,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
) )
except ConfigValidationError as ex: except ConfigValidationError as ex:
raise ServiceValidationError( raise ServiceValidationError(
str(ex),
translation_domain=ex.translation_domain, translation_domain=ex.translation_domain,
translation_key=ex.translation_key, translation_key=ex.translation_key,
translation_placeholders=ex.translation_placeholders, translation_placeholders=ex.translation_placeholders,

View file

@ -179,7 +179,6 @@ class SelectEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
if not options or option not in options: if not options or option not in options:
friendly_options: str = ", ".join(options or []) friendly_options: str = ", ".join(options or [])
raise ServiceValidationError( raise ServiceValidationError(
f"Option {option} is not valid for {self.entity_id}",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="not_valid_option", translation_key="not_valid_option",
translation_placeholders={ translation_placeholders={

View file

@ -264,10 +264,6 @@ def _attach_file(hass, atch_name, content_id=""):
file_name = os.path.basename(atch_name) file_name = os.path.basename(atch_name)
url = "https://www.home-assistant.io/docs/configuration/basic/" url = "https://www.home-assistant.io/docs/configuration/basic/"
raise ServiceValidationError( raise ServiceValidationError(
f"Cannot send email with attachment '{file_name}' "
f"from directory '{file_path}' which is not secure to load data from. "
f"Only folders added to `{allow_list}` are accessible. "
f"See {url} for more information.",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="remote_path_not_allowed", translation_key="remote_path_not_allowed",
translation_placeholders={ translation_placeholders={

View file

@ -112,7 +112,6 @@ class TessieCableLockEntity(TessieEntity, LockEntity):
async def async_lock(self, **kwargs: Any) -> None: async def async_lock(self, **kwargs: Any) -> None:
"""Charge cable Lock cannot be manually locked.""" """Charge cable Lock cannot be manually locked."""
raise ServiceValidationError( raise ServiceValidationError(
"Insert cable to lock",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="no_cable", translation_key="no_cable",
) )

View file

@ -107,7 +107,6 @@ def _validate_supported_features(
continue continue
if not supported_features or not supported_features & desc.required_feature: if not supported_features or not supported_features & desc.required_feature:
raise ServiceValidationError( raise ServiceValidationError(
f"Entity does not support setting field '{desc.service_field}'",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="update_field_not_supported", translation_key="update_field_not_supported",
translation_placeholders={"service_field": desc.service_field}, translation_placeholders={"service_field": desc.service_field},
@ -485,7 +484,6 @@ async def _async_update_todo_item(entity: TodoListEntity, call: ServiceCall) ->
found = _find_by_uid_or_summary(item, entity.todo_items) found = _find_by_uid_or_summary(item, entity.todo_items)
if not found: if not found:
raise ServiceValidationError( raise ServiceValidationError(
f"Unable to find To-do item '{item}'",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="item_not_found", translation_key="item_not_found",
translation_placeholders={"item": item}, translation_placeholders={"item": item},
@ -518,7 +516,6 @@ async def _async_remove_todo_items(entity: TodoListEntity, call: ServiceCall) ->
found = _find_by_uid_or_summary(item, entity.todo_items) found = _find_by_uid_or_summary(item, entity.todo_items)
if not found or not found.uid: if not found or not found.uid:
raise ServiceValidationError( raise ServiceValidationError(
f"Unable to find To-do item '{item}'",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="item_not_found", translation_key="item_not_found",
translation_placeholders={"item": item}, translation_placeholders={"item": item},

View file

@ -368,8 +368,6 @@ class WaterHeaterEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
"""Handle a set target operation mode service call.""" """Handle a set target operation mode service call."""
if self.operation_list is None: if self.operation_list is None:
raise ServiceValidationError( raise ServiceValidationError(
f"Operation mode {operation_mode} not valid for "
f"entity {self.entity_id}. The operation list is not defined",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="operation_list_not_defined", translation_key="operation_list_not_defined",
translation_placeholders={ translation_placeholders={
@ -380,9 +378,6 @@ class WaterHeaterEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
if operation_mode not in self.operation_list: if operation_mode not in self.operation_list:
operation_list = ", ".join(self.operation_list) operation_list = ", ".join(self.operation_list)
raise ServiceValidationError( raise ServiceValidationError(
f"Operation mode {operation_mode} not valid for "
f"entity {self.entity_id}. Valid "
f"operation modes are: {operation_list}",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="not_valid_operation_mode", translation_key="not_valid_operation_mode",
translation_placeholders={ translation_placeholders={

View file

@ -36,7 +36,6 @@ def async_register_services(hass: HomeAssistant) -> None:
break break
if entry is None or entry.state == ConfigEntryState.NOT_LOADED: if entry is None or entry.state == ConfigEntryState.NOT_LOADED:
raise ServiceValidationError( raise ServiceValidationError(
"Config entry not found or not loaded!",
translation_domain=DOMAIN, translation_domain=DOMAIN,
translation_key="invalid_config_entry", translation_key="invalid_config_entry",
) )

View file

@ -1,5 +1,7 @@
"""Tests for the services provided by the EnergyZero integration.""" """Tests for the services provided by the EnergyZero integration."""
import re
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
import voluptuous as vol import voluptuous as vol
@ -101,7 +103,7 @@ def config_entry_data(
"start": "incorrect date", "start": "incorrect date",
}, },
ServiceValidationError, ServiceValidationError,
"Invalid datetime provided.", "Invalid date provided. Got incorrect date",
), ),
( (
{"config_entry": True}, {"config_entry": True},
@ -110,7 +112,7 @@ def config_entry_data(
"end": "incorrect date", "end": "incorrect date",
}, },
ServiceValidationError, ServiceValidationError,
"Invalid datetime provided.", "Invalid date provided. Got incorrect date",
), ),
], ],
indirect=["config_entry_data"], indirect=["config_entry_data"],
@ -125,7 +127,7 @@ async def test_service_validation(
) -> None: ) -> None:
"""Test the EnergyZero Service validation.""" """Test the EnergyZero Service validation."""
with pytest.raises(error, match=error_message): with pytest.raises(error) as exc:
await hass.services.async_call( await hass.services.async_call(
DOMAIN, DOMAIN,
service, service,
@ -133,6 +135,7 @@ async def test_service_validation(
blocking=True, blocking=True,
return_response=True, return_response=True,
) )
assert re.match(error_message, str(exc.value))
@pytest.mark.usefixtures("init_integration") @pytest.mark.usefixtures("init_integration")

View file

@ -550,8 +550,8 @@ async def test_service_call_with_template_topic_renders_invalid_topic(
blocking=True, blocking=True,
) )
assert str(exc.value) == ( assert str(exc.value) == (
"Unable to publish: topic template 'test/{{ '+' if True else 'topic' }}/topic' " "Unable to publish: topic template `test/{{ '+' if True else 'topic' }}/topic` "
"produced an invalid topic 'test/+/topic' after rendering " "produced an invalid topic `test/+/topic` after rendering "
"(Wildcards cannot be used in topic names)" "(Wildcards cannot be used in topic names)"
) )
assert not mqtt_mock.async_publish.called assert not mqtt_mock.async_publish.called

View file

@ -348,12 +348,12 @@ async def test_add_item_service_raises(
( (
{"item": "Submit forms", "description": "Submit tax forms"}, {"item": "Submit forms", "description": "Submit tax forms"},
ServiceValidationError, ServiceValidationError,
"does not support setting field 'description'", "does not support setting field: description",
), ),
( (
{"item": "Submit forms", "due_date": "2023-11-17"}, {"item": "Submit forms", "due_date": "2023-11-17"},
ServiceValidationError, ServiceValidationError,
"does not support setting field 'due_date'", "does not support setting field: due_date",
), ),
( (
{ {
@ -361,7 +361,7 @@ async def test_add_item_service_raises(
"due_datetime": f"2023-11-17T17:00:00{TEST_OFFSET}", "due_datetime": f"2023-11-17T17:00:00{TEST_OFFSET}",
}, },
ServiceValidationError, ServiceValidationError,
"does not support setting field 'due_datetime'", "does not support setting field: due_datetime",
), ),
], ],
) )
@ -376,7 +376,7 @@ async def test_add_item_service_invalid_input(
await create_mock_platform(hass, [test_entity]) await create_mock_platform(hass, [test_entity])
with pytest.raises(expected_exception, match=expected_error): with pytest.raises(expected_exception) as exc:
await hass.services.async_call( await hass.services.async_call(
DOMAIN, DOMAIN,
"add_item", "add_item",
@ -385,6 +385,8 @@ async def test_add_item_service_invalid_input(
blocking=True, blocking=True,
) )
assert expected_error in str(exc.value)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("supported_entity_feature", "item_data", "expected_item"), ("supported_entity_feature", "item_data", "expected_item"),

View file

@ -175,7 +175,7 @@ async def test_operation_mode_validation(
DOMAIN, SERVICE_SET_OPERATION_MODE, data, blocking=True DOMAIN, SERVICE_SET_OPERATION_MODE, data, blocking=True
) )
assert ( assert (
str(exc.value) == "Operation mode test not valid for entity water_heater.test. " str(exc.value) == "Operation mode test is not valid for water_heater.test. "
"The operation list is not defined" "The operation list is not defined"
) )
assert exc.value.translation_domain == DOMAIN assert exc.value.translation_domain == DOMAIN
@ -191,7 +191,7 @@ async def test_operation_mode_validation(
DOMAIN, SERVICE_SET_OPERATION_MODE, data, blocking=True DOMAIN, SERVICE_SET_OPERATION_MODE, data, blocking=True
) )
assert ( assert (
str(exc.value) == "Operation mode test not valid for entity water_heater.test. " str(exc.value) == "Operation mode test is not valid for water_heater.test. "
"Valid operation modes are: gas, eco" "Valid operation modes are: gas, eco"
) )
assert exc.value.translation_domain == DOMAIN assert exc.value.translation_domain == DOMAIN