diff --git a/homeassistant/components/api/__init__.py b/homeassistant/components/api/__init__.py index 56a07a6bcf0..2a67308a0b8 100644 --- a/homeassistant/components/api/__init__.py +++ b/homeassistant/components/api/__init__.py @@ -1,5 +1,6 @@ """Rest API for Home Assistant.""" import asyncio +from functools import lru_cache from http import HTTPStatus import logging @@ -350,6 +351,9 @@ class APIComponentsView(HomeAssistantView): return self.json(request.app["hass"].config.components) +_cached_template = lru_cache(template.Template) + + class APITemplateView(HomeAssistantView): """View to handle Template requests.""" @@ -362,7 +366,8 @@ class APITemplateView(HomeAssistantView): raise Unauthorized() try: data = await request.json() - tpl = template.Template(data["template"], request.app["hass"]) + tpl = _cached_template(data["template"]) + tpl.hass = request.app["hass"] return tpl.async_render(variables=data.get("variables"), parse_result=False) except (ValueError, TemplateError) as ex: return self.json_message( diff --git a/homeassistant/components/mobile_app/webhook.py b/homeassistant/components/mobile_app/webhook.py index c7fc375008a..648efea9d30 100644 --- a/homeassistant/components/mobile_app/webhook.py +++ b/homeassistant/components/mobile_app/webhook.py @@ -4,7 +4,7 @@ from __future__ import annotations import asyncio from collections.abc import Callable, Coroutine from contextlib import suppress -from functools import wraps +from functools import lru_cache, wraps from http import HTTPStatus import logging import secrets @@ -365,6 +365,9 @@ async def webhook_stream_camera( return webhook_response(resp, registration=config_entry.data) +_cached_template = lru_cache(template.Template) + + @WEBHOOK_COMMANDS.register("render_template") @validate_schema( { @@ -381,7 +384,8 @@ async def webhook_render_template( resp = {} for key, item in data.items(): try: - tpl = template.Template(item[ATTR_TEMPLATE], hass) + tpl = _cached_template(item[ATTR_TEMPLATE]) + tpl.hass = hass resp[key] = tpl.async_render(item.get(ATTR_TEMPLATE_VARIABLES)) except TemplateError as ex: resp[key] = {"error": str(ex)} diff --git a/homeassistant/components/websocket_api/commands.py b/homeassistant/components/websocket_api/commands.py index e8008eb49b6..b002c834f01 100644 --- a/homeassistant/components/websocket_api/commands.py +++ b/homeassistant/components/websocket_api/commands.py @@ -4,6 +4,7 @@ from __future__ import annotations from collections.abc import Callable from contextlib import suppress import datetime as dt +from functools import lru_cache import json from typing import Any, cast @@ -424,6 +425,9 @@ def handle_ping( connection.send_message(pong_message(msg["id"])) +_cached_template = lru_cache(template.Template) + + @decorators.websocket_command( { vol.Required("type"): "render_template", @@ -440,7 +444,8 @@ async def handle_render_template( ) -> None: """Handle render_template command.""" template_str = msg["template"] - template_obj = template.Template(template_str, hass) + template_obj = _cached_template(template_str) + template_obj.hass = hass variables = msg.get("variables") timeout = msg.get("timeout") info = None