Skip to content

Commit d7ad0cb

Browse files
authored
Modernize template image (home-assistant#157255)
1 parent 159a8d3 commit d7ad0cb

File tree

1 file changed

+30
-19
lines changed
  • homeassistant/components/template

1 file changed

+30
-19
lines changed

homeassistant/components/template/image.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
from . import TriggerUpdateCoordinator
2828
from .const import CONF_PICTURE
29+
from .entity import AbstractTemplateEntity
2930
from .helpers import async_setup_template_entry, async_setup_template_platform
3031
from .schemas import (
3132
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
@@ -93,12 +94,30 @@ async def async_setup_entry(
9394
)
9495

9596

96-
class StateImageEntity(TemplateEntity, ImageEntity):
97+
class AbstractTemplateImage(AbstractTemplateEntity, ImageEntity):
98+
"""Representation of a template image features."""
99+
100+
_entity_id_format = ENTITY_ID_FORMAT
101+
_attr_image_url: str | None = None
102+
103+
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
104+
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
105+
def __init__(self, hass: HomeAssistant, config: dict[str, Any]) -> None: # pylint: disable=super-init-not-called
106+
"""Initialize the features."""
107+
ImageEntity.__init__(self, hass, config[CONF_VERIFY_SSL])
108+
self._url_template = config[CONF_URL]
109+
self._has_picture_template = CONF_PICTURE in config
110+
111+
def _handle_state(self, result: Any) -> None:
112+
self._attr_image_last_updated = dt_util.utcnow()
113+
self._cached_image = None
114+
self._attr_image_url = result
115+
116+
117+
class StateImageEntity(TemplateEntity, AbstractTemplateImage):
97118
"""Representation of a template image."""
98119

99120
_attr_should_poll = False
100-
_attr_image_url: str | None = None
101-
_entity_id_format = ENTITY_ID_FORMAT
102121

103122
def __init__(
104123
self,
@@ -108,13 +127,12 @@ def __init__(
108127
) -> None:
109128
"""Initialize the image."""
110129
TemplateEntity.__init__(self, hass, config, unique_id)
111-
ImageEntity.__init__(self, hass, config[CONF_VERIFY_SSL])
112-
self._url_template = config[CONF_URL]
130+
AbstractTemplateImage.__init__(self, hass, config)
113131

114132
@property
115133
def entity_picture(self) -> str | None:
116134
"""Return entity picture."""
117-
if self._entity_picture_template:
135+
if self._has_picture_template:
118136
return TemplateEntity.entity_picture.__get__(self)
119137
# mypy doesn't know about fget: https://github.com/python/mypy/issues/6185
120138
return ImageEntity.entity_picture.fget(self) # type: ignore[attr-defined]
@@ -124,9 +142,7 @@ def _update_url(self, result):
124142
if isinstance(result, TemplateError):
125143
self._attr_image_url = None
126144
return
127-
self._attr_image_last_updated = dt_util.utcnow()
128-
self._cached_image = None
129-
self._attr_image_url = result
145+
self._handle_state(result)
130146

131147
@callback
132148
def _async_setup_templates(self) -> None:
@@ -135,12 +151,9 @@ def _async_setup_templates(self) -> None:
135151
super()._async_setup_templates()
136152

137153

138-
class TriggerImageEntity(TriggerEntity, ImageEntity):
154+
class TriggerImageEntity(TriggerEntity, AbstractTemplateImage):
139155
"""Image entity based on trigger data."""
140156

141-
_attr_image_url: str | None = None
142-
_entity_id_format = ENTITY_ID_FORMAT
143-
144157
domain = IMAGE_DOMAIN
145158
extra_template_keys = (CONF_URL,)
146159

@@ -152,20 +165,18 @@ def __init__(
152165
) -> None:
153166
"""Initialize the entity."""
154167
TriggerEntity.__init__(self, hass, coordinator, config)
155-
ImageEntity.__init__(self, hass, config[CONF_VERIFY_SSL])
168+
AbstractTemplateImage.__init__(self, hass, config)
156169

157170
@property
158171
def entity_picture(self) -> str | None:
159172
"""Return entity picture."""
173+
if self._has_picture_template:
174+
return TriggerEntity.entity_picture.__get__(self)
160175
# mypy doesn't know about fget: https://github.com/python/mypy/issues/6185
161-
if CONF_PICTURE in self._config:
162-
return TriggerEntity.entity_picture.fget(self) # type: ignore[attr-defined]
163176
return ImageEntity.entity_picture.fget(self) # type: ignore[attr-defined]
164177

165178
@callback
166179
def _process_data(self) -> None:
167180
"""Process new data."""
168181
super()._process_data()
169-
self._attr_image_last_updated = dt_util.utcnow()
170-
self._cached_image = None
171-
self._attr_image_url = self._rendered.get(CONF_URL)
182+
self._handle_state(self._rendered.get(CONF_URL))

0 commit comments

Comments
 (0)