Allow specifying a custom log function for template render (#99572)
* Allow specifying a custom log function for template render * Bypass template cache when reporting errors + fix tests * Send errors as events * Fix logic for creating new TemplateEnvironment * Add strict mode back * Only send error events if report_errors is True * Force test of websocket_api only * Debug test * Run pytest with higher verbosity * Timeout after 1 minute, enable syslog output * Adjust timeout * Add debug logs * Fix unsafe call to WebSocketHandler._send_message * Remove debug code * Improve test coverage * Revert accidental change * Include severity in error events * Remove redundant information from error events
This commit is contained in:
parent
f41b045244
commit
48f7924e9e
5 changed files with 374 additions and 84 deletions
|
@ -5,6 +5,7 @@ from collections.abc import Callable
|
|||
import datetime as dt
|
||||
from functools import lru_cache, partial
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
|
||||
import voluptuous as vol
|
||||
|
@ -505,6 +506,7 @@ def _cached_template(template_str: str, hass: HomeAssistant) -> template.Templat
|
|||
vol.Optional("variables"): dict,
|
||||
vol.Optional("timeout"): vol.Coerce(float),
|
||||
vol.Optional("strict", default=False): bool,
|
||||
vol.Optional("report_errors", default=False): bool,
|
||||
}
|
||||
)
|
||||
@decorators.async_response
|
||||
|
@ -513,14 +515,32 @@ async def handle_render_template(
|
|||
) -> None:
|
||||
"""Handle render_template command."""
|
||||
template_str = msg["template"]
|
||||
template_obj = _cached_template(template_str, hass)
|
||||
report_errors: bool = msg["report_errors"]
|
||||
if report_errors:
|
||||
template_obj = template.Template(template_str, hass)
|
||||
else:
|
||||
template_obj = _cached_template(template_str, hass)
|
||||
variables = msg.get("variables")
|
||||
timeout = msg.get("timeout")
|
||||
|
||||
@callback
|
||||
def _error_listener(level: int, template_error: str) -> None:
|
||||
connection.send_message(
|
||||
messages.event_message(
|
||||
msg["id"],
|
||||
{"error": template_error, "level": logging.getLevelName(level)},
|
||||
)
|
||||
)
|
||||
|
||||
@callback
|
||||
def _thread_safe_error_listener(level: int, template_error: str) -> None:
|
||||
hass.loop.call_soon_threadsafe(_error_listener, level, template_error)
|
||||
|
||||
if timeout:
|
||||
try:
|
||||
log_fn = _thread_safe_error_listener if report_errors else None
|
||||
timed_out = await template_obj.async_render_will_timeout(
|
||||
timeout, variables, strict=msg["strict"]
|
||||
timeout, variables, strict=msg["strict"], log_fn=log_fn
|
||||
)
|
||||
except TemplateError as ex:
|
||||
connection.send_error(msg["id"], const.ERR_TEMPLATE_ERROR, str(ex))
|
||||
|
@ -542,7 +562,11 @@ async def handle_render_template(
|
|||
track_template_result = updates.pop()
|
||||
result = track_template_result.result
|
||||
if isinstance(result, TemplateError):
|
||||
connection.send_error(msg["id"], const.ERR_TEMPLATE_ERROR, str(result))
|
||||
if not report_errors:
|
||||
return
|
||||
connection.send_message(
|
||||
messages.event_message(msg["id"], {"error": str(result)})
|
||||
)
|
||||
return
|
||||
|
||||
connection.send_message(
|
||||
|
@ -552,12 +576,14 @@ async def handle_render_template(
|
|||
)
|
||||
|
||||
try:
|
||||
log_fn = _error_listener if report_errors else None
|
||||
info = async_track_template_result(
|
||||
hass,
|
||||
[TrackTemplate(template_obj, variables)],
|
||||
_template_listener,
|
||||
raise_on_template_error=True,
|
||||
strict=msg["strict"],
|
||||
log_fn=log_fn,
|
||||
)
|
||||
except TemplateError as ex:
|
||||
connection.send_error(msg["id"], const.ERR_TEMPLATE_ERROR, str(ex))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue