Remove notify support for templates (#122820)
This commit is contained in:
parent
6967c70580
commit
8d0dda6523
5 changed files with 15 additions and 79 deletions
|
@ -18,7 +18,6 @@ import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import EntityDescription
|
from homeassistant.helpers.entity import EntityDescription
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
from homeassistant.helpers.template import Template
|
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
|
@ -39,7 +38,6 @@ from .legacy import ( # noqa: F401
|
||||||
async_reload,
|
async_reload,
|
||||||
async_reset_platform,
|
async_reset_platform,
|
||||||
async_setup_legacy,
|
async_setup_legacy,
|
||||||
check_templates_warn,
|
|
||||||
)
|
)
|
||||||
from .repairs import migrate_notify_issue # noqa: F401
|
from .repairs import migrate_notify_issue # noqa: F401
|
||||||
|
|
||||||
|
@ -90,22 +88,14 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
|
|
||||||
async def persistent_notification(service: ServiceCall) -> None:
|
async def persistent_notification(service: ServiceCall) -> None:
|
||||||
"""Send notification via the built-in persistent_notify integration."""
|
"""Send notification via the built-in persistent_notify integration."""
|
||||||
message: Template = service.data[ATTR_MESSAGE]
|
message: str = service.data[ATTR_MESSAGE]
|
||||||
check_templates_warn(hass, message)
|
title: str | None = service.data.get(ATTR_TITLE)
|
||||||
|
|
||||||
title = None
|
|
||||||
title_tpl: Template | None
|
|
||||||
if title_tpl := service.data.get(ATTR_TITLE):
|
|
||||||
check_templates_warn(hass, title_tpl)
|
|
||||||
title = title_tpl.async_render(parse_result=False)
|
|
||||||
|
|
||||||
notification_id = None
|
notification_id = None
|
||||||
if data := service.data.get(ATTR_DATA):
|
if data := service.data.get(ATTR_DATA):
|
||||||
notification_id = data.get(pn.ATTR_NOTIFICATION_ID)
|
notification_id = data.get(pn.ATTR_NOTIFICATION_ID)
|
||||||
|
|
||||||
pn.async_create(
|
pn.async_create(hass, message, title, notification_id)
|
||||||
hass, message.async_render(parse_result=False), title, notification_id
|
|
||||||
)
|
|
||||||
|
|
||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
|
|
@ -30,8 +30,8 @@ SERVICE_PERSISTENT_NOTIFICATION = "persistent_notification"
|
||||||
|
|
||||||
NOTIFY_SERVICE_SCHEMA = vol.Schema(
|
NOTIFY_SERVICE_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(ATTR_MESSAGE): cv.template,
|
vol.Required(ATTR_MESSAGE): cv.string,
|
||||||
vol.Optional(ATTR_TITLE): cv.template,
|
vol.Optional(ATTR_TITLE): cv.string,
|
||||||
vol.Optional(ATTR_TARGET): vol.All(cv.ensure_list, [cv.string]),
|
vol.Optional(ATTR_TARGET): vol.All(cv.ensure_list, [cv.string]),
|
||||||
vol.Optional(ATTR_DATA): dict,
|
vol.Optional(ATTR_DATA): dict,
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
from homeassistant.helpers.service import async_set_service_schema
|
from homeassistant.helpers.service import async_set_service_schema
|
||||||
from homeassistant.helpers.template import Template
|
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.loader import async_get_integration, bind_hass
|
from homeassistant.loader import async_get_integration, bind_hass
|
||||||
from homeassistant.setup import (
|
from homeassistant.setup import (
|
||||||
|
@ -155,19 +154,6 @@ def async_setup_legacy(
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@callback
|
|
||||||
def check_templates_warn(hass: HomeAssistant, tpl: Template) -> None:
|
|
||||||
"""Warn user that passing templates to notify service is deprecated."""
|
|
||||||
if tpl.is_static or hass.data.get("notify_template_warned"):
|
|
||||||
return
|
|
||||||
|
|
||||||
hass.data["notify_template_warned"] = True
|
|
||||||
LOGGER.warning(
|
|
||||||
"Passing templates to notify service is deprecated and will be removed in"
|
|
||||||
" 2021.12. Automations and scripts handle templates automatically"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
async def async_reload(hass: HomeAssistant, integration_name: str) -> None:
|
async def async_reload(hass: HomeAssistant, integration_name: str) -> None:
|
||||||
"""Register notify services for an integration."""
|
"""Register notify services for an integration."""
|
||||||
|
@ -255,19 +241,17 @@ class BaseNotificationService:
|
||||||
async def _async_notify_message_service(self, service: ServiceCall) -> None:
|
async def _async_notify_message_service(self, service: ServiceCall) -> None:
|
||||||
"""Handle sending notification message service calls."""
|
"""Handle sending notification message service calls."""
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
message: Template = service.data[ATTR_MESSAGE]
|
message: str = service.data[ATTR_MESSAGE]
|
||||||
title: Template | None
|
title: str | None
|
||||||
if title := service.data.get(ATTR_TITLE):
|
if title := service.data.get(ATTR_TITLE):
|
||||||
check_templates_warn(self.hass, title)
|
kwargs[ATTR_TITLE] = title
|
||||||
kwargs[ATTR_TITLE] = title.async_render(parse_result=False)
|
|
||||||
|
|
||||||
if self.registered_targets.get(service.service) is not None:
|
if self.registered_targets.get(service.service) is not None:
|
||||||
kwargs[ATTR_TARGET] = [self.registered_targets[service.service]]
|
kwargs[ATTR_TARGET] = [self.registered_targets[service.service]]
|
||||||
elif service.data.get(ATTR_TARGET) is not None:
|
elif service.data.get(ATTR_TARGET) is not None:
|
||||||
kwargs[ATTR_TARGET] = service.data.get(ATTR_TARGET)
|
kwargs[ATTR_TARGET] = service.data.get(ATTR_TARGET)
|
||||||
|
|
||||||
check_templates_warn(self.hass, message)
|
kwargs[ATTR_MESSAGE] = message
|
||||||
kwargs[ATTR_MESSAGE] = message.async_render(parse_result=False)
|
|
||||||
kwargs[ATTR_DATA] = service.data.get(ATTR_DATA)
|
kwargs[ATTR_DATA] = service.data.get(ATTR_DATA)
|
||||||
|
|
||||||
await self.async_send_message(**kwargs)
|
await self.async_send_message(**kwargs)
|
||||||
|
|
|
@ -165,8 +165,7 @@ async def test_login_flow_validates_mfa(hass: HomeAssistant) -> None:
|
||||||
assert notify_call.domain == "notify"
|
assert notify_call.domain == "notify"
|
||||||
assert notify_call.service == "test-notify"
|
assert notify_call.service == "test-notify"
|
||||||
message = notify_call.data["message"]
|
message = notify_call.data["message"]
|
||||||
message.hass = hass
|
assert MOCK_CODE in message
|
||||||
assert MOCK_CODE in message.async_render()
|
|
||||||
|
|
||||||
with patch("pyotp.HOTP.verify", return_value=False):
|
with patch("pyotp.HOTP.verify", return_value=False):
|
||||||
result = await hass.auth.login_flow.async_configure(
|
result = await hass.auth.login_flow.async_configure(
|
||||||
|
@ -224,8 +223,7 @@ async def test_login_flow_validates_mfa(hass: HomeAssistant) -> None:
|
||||||
assert notify_call.domain == "notify"
|
assert notify_call.domain == "notify"
|
||||||
assert notify_call.service == "test-notify"
|
assert notify_call.service == "test-notify"
|
||||||
message = notify_call.data["message"]
|
message = notify_call.data["message"]
|
||||||
message.hass = hass
|
assert MOCK_CODE in message
|
||||||
assert MOCK_CODE in message.async_render()
|
|
||||||
|
|
||||||
with patch("pyotp.HOTP.verify", return_value=True):
|
with patch("pyotp.HOTP.verify", return_value=True):
|
||||||
result = await hass.auth.login_flow.async_configure(
|
result = await hass.auth.login_flow.async_configure(
|
||||||
|
@ -264,8 +262,7 @@ async def test_setup_user_notify_service(hass: HomeAssistant) -> None:
|
||||||
assert notify_call.domain == "notify"
|
assert notify_call.domain == "notify"
|
||||||
assert notify_call.service == "test1"
|
assert notify_call.service == "test1"
|
||||||
message = notify_call.data["message"]
|
message = notify_call.data["message"]
|
||||||
message.hass = hass
|
assert MOCK_CODE in message
|
||||||
assert MOCK_CODE in message.async_render()
|
|
||||||
|
|
||||||
with patch("pyotp.HOTP.at", return_value=MOCK_CODE_2):
|
with patch("pyotp.HOTP.at", return_value=MOCK_CODE_2):
|
||||||
step = await flow.async_step_setup({"code": "invalid"})
|
step = await flow.async_step_setup({"code": "invalid"})
|
||||||
|
@ -281,8 +278,7 @@ async def test_setup_user_notify_service(hass: HomeAssistant) -> None:
|
||||||
assert notify_call.domain == "notify"
|
assert notify_call.domain == "notify"
|
||||||
assert notify_call.service == "test1"
|
assert notify_call.service == "test1"
|
||||||
message = notify_call.data["message"]
|
message = notify_call.data["message"]
|
||||||
message.hass = hass
|
assert MOCK_CODE_2 in message
|
||||||
assert MOCK_CODE_2 in message.async_render()
|
|
||||||
|
|
||||||
with patch("pyotp.HOTP.verify", return_value=True):
|
with patch("pyotp.HOTP.verify", return_value=True):
|
||||||
step = await flow.async_step_setup({"code": MOCK_CODE_2})
|
step = await flow.async_step_setup({"code": MOCK_CODE_2})
|
||||||
|
|
|
@ -19,7 +19,7 @@ from homeassistant.helpers.reload import async_setup_reload_service
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import MockPlatform, async_get_persistent_notifications, mock_platform
|
from tests.common import MockPlatform, mock_platform
|
||||||
|
|
||||||
|
|
||||||
class NotificationService(notify.BaseNotificationService):
|
class NotificationService(notify.BaseNotificationService):
|
||||||
|
@ -186,24 +186,6 @@ async def test_remove_targets(hass: HomeAssistant) -> None:
|
||||||
assert test.registered_targets == {"test_c": 1}
|
assert test.registered_targets == {"test_c": 1}
|
||||||
|
|
||||||
|
|
||||||
async def test_warn_template(
|
|
||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
|
||||||
) -> None:
|
|
||||||
"""Test warning when template used."""
|
|
||||||
assert await async_setup_component(hass, "notify", {})
|
|
||||||
|
|
||||||
await hass.services.async_call(
|
|
||||||
"notify",
|
|
||||||
"persistent_notification",
|
|
||||||
{"message": "{{ 1 + 1 }}", "title": "Test notif {{ 1 + 1 }}"},
|
|
||||||
blocking=True,
|
|
||||||
)
|
|
||||||
# We should only log it once
|
|
||||||
assert caplog.text.count("Passing templates to notify service is deprecated") == 1
|
|
||||||
notifications = async_get_persistent_notifications(hass)
|
|
||||||
assert len(notifications) == 1
|
|
||||||
|
|
||||||
|
|
||||||
async def test_invalid_platform(
|
async def test_invalid_platform(
|
||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, tmp_path: Path
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, tmp_path: Path
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -550,27 +532,11 @@ async def test_sending_none_message(hass: HomeAssistant, tmp_path: Path) -> None
|
||||||
notify.DOMAIN, notify.SERVICE_NOTIFY, {notify.ATTR_MESSAGE: None}
|
notify.DOMAIN, notify.SERVICE_NOTIFY, {notify.ATTR_MESSAGE: None}
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
str(exc.value)
|
str(exc.value) == "string value is None for dictionary value @ data['message']"
|
||||||
== "template value is None for dictionary value @ data['message']"
|
|
||||||
)
|
)
|
||||||
send_message_mock.assert_not_called()
|
send_message_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
async def test_sending_templated_message(hass: HomeAssistant, tmp_path: Path) -> None:
|
|
||||||
"""Send a templated message."""
|
|
||||||
send_message_mock = await help_setup_notify(hass, tmp_path)
|
|
||||||
hass.states.async_set("sensor.temperature", 10)
|
|
||||||
data = {
|
|
||||||
notify.ATTR_MESSAGE: "{{states.sensor.temperature.state}}",
|
|
||||||
notify.ATTR_TITLE: "{{ states.sensor.temperature.name }}",
|
|
||||||
}
|
|
||||||
await hass.services.async_call(notify.DOMAIN, notify.SERVICE_NOTIFY, data)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
send_message_mock.assert_called_once_with(
|
|
||||||
"10", {"title": "temperature", "data": None}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_method_forwards_correct_data(
|
async def test_method_forwards_correct_data(
|
||||||
hass: HomeAssistant, tmp_path: Path
|
hass: HomeAssistant, tmp_path: Path
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue