Skip to content

Commit c058561

Browse files
authored
Add initalize for abstract template entities (home-assistant#147504)
1 parent b89b248 commit c058561

File tree

20 files changed

+106
-145
lines changed

20 files changed

+106
-145
lines changed

homeassistant/components/template/alarm_control_panel.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
from homeassistant.core import HomeAssistant, callback
3333
from homeassistant.exceptions import TemplateError
3434
from homeassistant.helpers import config_validation as cv, selector, template
35-
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
36-
from homeassistant.helpers.entity import async_generate_entity_id
3735
from homeassistant.helpers.entity_platform import (
3836
AddConfigEntryEntitiesCallback,
3937
AddEntitiesCallback,
@@ -42,7 +40,7 @@
4240
from homeassistant.helpers.script import Script
4341
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
4442

45-
from .const import CONF_OBJECT_ID, DOMAIN
43+
from .const import DOMAIN
4644
from .coordinator import TriggerUpdateCoordinator
4745
from .entity import AbstractTemplateEntity
4846
from .helpers import async_setup_template_platform
@@ -213,6 +211,8 @@ class AbstractTemplateAlarmControlPanel(
213211
):
214212
"""Representation of a templated Alarm Control Panel features."""
215213

214+
_entity_id_format = ENTITY_ID_FORMAT
215+
216216
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
217217
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
218218
def __init__(self, config: dict[str, Any]) -> None: # pylint: disable=super-init-not-called
@@ -363,12 +363,8 @@ def __init__(
363363
unique_id: str | None,
364364
) -> None:
365365
"""Initialize the panel."""
366-
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
366+
TemplateEntity.__init__(self, hass, config, unique_id)
367367
AbstractTemplateAlarmControlPanel.__init__(self, config)
368-
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
369-
self.entity_id = async_generate_entity_id(
370-
ENTITY_ID_FORMAT, object_id, hass=hass
371-
)
372368
name = self._attr_name
373369
if TYPE_CHECKING:
374370
assert name is not None
@@ -379,11 +375,6 @@ def __init__(
379375
self.add_script(action_id, action_config, name, DOMAIN)
380376
self._attr_supported_features |= supported_feature
381377

382-
self._attr_device_info = async_device_info_to_link_from_device_id(
383-
hass,
384-
config.get(CONF_DEVICE_ID),
385-
)
386-
387378
async def async_added_to_hass(self) -> None:
388379
"""Restore last state."""
389380
await super().async_added_to_hass()
@@ -434,11 +425,6 @@ def __init__(
434425
self.add_script(action_id, action_config, name, DOMAIN)
435426
self._attr_supported_features |= supported_feature
436427

437-
self._attr_device_info = async_device_info_to_link_from_device_id(
438-
hass,
439-
config.get(CONF_DEVICE_ID),
440-
)
441-
442428
async def async_added_to_hass(self) -> None:
443429
"""Restore last state."""
444430
await super().async_added_to_hass()

homeassistant/components/template/binary_sensor.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@
3939
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
4040
from homeassistant.exceptions import TemplateError
4141
from homeassistant.helpers import config_validation as cv, selector, template
42-
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
43-
from homeassistant.helpers.entity import async_generate_entity_id
4442
from homeassistant.helpers.entity_platform import (
4543
AddConfigEntryEntitiesCallback,
4644
AddEntitiesCallback,
@@ -51,7 +49,7 @@
5149
from homeassistant.util import dt as dt_util
5250

5351
from . import TriggerUpdateCoordinator
54-
from .const import CONF_AVAILABILITY_TEMPLATE, CONF_OBJECT_ID
52+
from .const import CONF_AVAILABILITY_TEMPLATE
5553
from .helpers import async_setup_template_platform
5654
from .template_entity import TEMPLATE_ENTITY_COMMON_SCHEMA, TemplateEntity
5755
from .trigger_entity import TriggerEntity
@@ -161,6 +159,7 @@ class StateBinarySensorEntity(TemplateEntity, BinarySensorEntity, RestoreEntity)
161159
"""A virtual binary sensor that triggers from another sensor."""
162160

163161
_attr_should_poll = False
162+
_entity_id_format = ENTITY_ID_FORMAT
164163

165164
def __init__(
166165
self,
@@ -169,11 +168,7 @@ def __init__(
169168
unique_id: str | None,
170169
) -> None:
171170
"""Initialize the Template binary sensor."""
172-
super().__init__(hass, config=config, unique_id=unique_id)
173-
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
174-
self.entity_id = async_generate_entity_id(
175-
ENTITY_ID_FORMAT, object_id, hass=hass
176-
)
171+
TemplateEntity.__init__(self, hass, config, unique_id)
177172

178173
self._attr_device_class = config.get(CONF_DEVICE_CLASS)
179174
self._template = config[CONF_STATE]
@@ -182,10 +177,6 @@ def __init__(
182177
self._delay_on_raw = config.get(CONF_DELAY_ON)
183178
self._delay_off = None
184179
self._delay_off_raw = config.get(CONF_DELAY_OFF)
185-
self._attr_device_info = async_device_info_to_link_from_device_id(
186-
hass,
187-
config.get(CONF_DEVICE_ID),
188-
)
189180

190181
async def async_added_to_hass(self) -> None:
191182
"""Restore state."""
@@ -258,6 +249,7 @@ def _set_state(_):
258249
class TriggerBinarySensorEntity(TriggerEntity, BinarySensorEntity, RestoreEntity):
259250
"""Sensor entity based on trigger data."""
260251

252+
_entity_id_format = ENTITY_ID_FORMAT
261253
domain = BINARY_SENSOR_DOMAIN
262254
extra_template_keys = (CONF_STATE,)
263255

homeassistant/components/template/button.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
from __future__ import annotations
44

55
import logging
6+
from typing import TYPE_CHECKING
67

78
import voluptuous as vol
89

910
from homeassistant.components.button import (
1011
DEVICE_CLASSES_SCHEMA,
1112
DOMAIN as BUTTON_DOMAIN,
13+
ENTITY_ID_FORMAT,
1214
ButtonEntity,
1315
)
1416
from homeassistant.config_entries import ConfigEntry
@@ -84,6 +86,7 @@ class StateButtonEntity(TemplateEntity, ButtonEntity):
8486
"""Representation of a template button."""
8587

8688
_attr_should_poll = False
89+
_entity_id_format = ENTITY_ID_FORMAT
8790

8891
def __init__(
8992
self,
@@ -92,8 +95,11 @@ def __init__(
9295
unique_id: str | None,
9396
) -> None:
9497
"""Initialize the button."""
95-
super().__init__(hass, config=config, unique_id=unique_id)
96-
assert self._attr_name is not None
98+
TemplateEntity.__init__(self, hass, config, unique_id)
99+
100+
if TYPE_CHECKING:
101+
assert self._attr_name is not None
102+
97103
# Scripts can be an empty list, therefore we need to check for None
98104
if (action := config.get(CONF_PRESS)) is not None:
99105
self.add_script(CONF_PRESS, action, self._attr_name, DOMAIN)

homeassistant/components/template/cover.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,11 @@
3232
from homeassistant.core import HomeAssistant, callback
3333
from homeassistant.exceptions import TemplateError
3434
from homeassistant.helpers import config_validation as cv, template
35-
from homeassistant.helpers.entity import async_generate_entity_id
3635
from homeassistant.helpers.entity_platform import AddEntitiesCallback
3736
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
3837

3938
from . import TriggerUpdateCoordinator
40-
from .const import CONF_OBJECT_ID, DOMAIN
39+
from .const import DOMAIN
4140
from .entity import AbstractTemplateEntity
4241
from .helpers import async_setup_template_platform
4342
from .template_entity import (
@@ -162,6 +161,8 @@ async def async_setup_platform(
162161
class AbstractTemplateCover(AbstractTemplateEntity, CoverEntity):
163162
"""Representation of a template cover features."""
164163

164+
_entity_id_format = ENTITY_ID_FORMAT
165+
165166
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
166167
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
167168
def __init__(self, config: dict[str, Any]) -> None: # pylint: disable=super-init-not-called
@@ -397,12 +398,8 @@ def __init__(
397398
unique_id,
398399
) -> None:
399400
"""Initialize the Template cover."""
400-
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
401+
TemplateEntity.__init__(self, hass, config, unique_id)
401402
AbstractTemplateCover.__init__(self, config)
402-
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
403-
self.entity_id = async_generate_entity_id(
404-
ENTITY_ID_FORMAT, object_id, hass=hass
405-
)
406403
name = self._attr_name
407404
if TYPE_CHECKING:
408405
assert name is not None

homeassistant/components/template/entity.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,39 @@
33
from collections.abc import Sequence
44
from typing import Any
55

6+
from homeassistant.const import CONF_DEVICE_ID
67
from homeassistant.core import Context, HomeAssistant, callback
7-
from homeassistant.helpers.entity import Entity
8+
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
9+
from homeassistant.helpers.entity import Entity, async_generate_entity_id
810
from homeassistant.helpers.script import Script, _VarsType
911
from homeassistant.helpers.template import TemplateStateFromEntityId
12+
from homeassistant.helpers.typing import ConfigType
13+
14+
from .const import CONF_OBJECT_ID
1015

1116

1217
class AbstractTemplateEntity(Entity):
1318
"""Actions linked to a template entity."""
1419

15-
def __init__(self, hass: HomeAssistant) -> None:
20+
_entity_id_format: str
21+
22+
def __init__(self, hass: HomeAssistant, config: ConfigType) -> None:
1623
"""Initialize the entity."""
1724

1825
self.hass = hass
1926
self._action_scripts: dict[str, Script] = {}
2027

28+
if self.hass:
29+
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
30+
self.entity_id = async_generate_entity_id(
31+
self._entity_id_format, object_id, hass=self.hass
32+
)
33+
34+
self._attr_device_info = async_device_info_to_link_from_device_id(
35+
self.hass,
36+
config.get(CONF_DEVICE_ID),
37+
)
38+
2139
@property
2240
def referenced_blueprint(self) -> str | None:
2341
"""Return referenced blueprint or None."""

homeassistant/components/template/fan.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,10 @@
3434
from homeassistant.core import HomeAssistant, callback
3535
from homeassistant.exceptions import TemplateError
3636
from homeassistant.helpers import config_validation as cv, template
37-
from homeassistant.helpers.entity import async_generate_entity_id
3837
from homeassistant.helpers.entity_platform import AddEntitiesCallback
3938
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
4039

41-
from .const import CONF_OBJECT_ID, DOMAIN
40+
from .const import DOMAIN
4241
from .coordinator import TriggerUpdateCoordinator
4342
from .entity import AbstractTemplateEntity
4443
from .helpers import async_setup_template_platform
@@ -154,6 +153,8 @@ async def async_setup_platform(
154153
class AbstractTemplateFan(AbstractTemplateEntity, FanEntity):
155154
"""Representation of a template fan features."""
156155

156+
_entity_id_format = ENTITY_ID_FORMAT
157+
157158
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
158159
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
159160
def __init__(self, config: dict[str, Any]) -> None: # pylint: disable=super-init-not-called
@@ -436,12 +437,8 @@ def __init__(
436437
unique_id,
437438
) -> None:
438439
"""Initialize the fan."""
439-
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
440+
TemplateEntity.__init__(self, hass, config, unique_id)
440441
AbstractTemplateFan.__init__(self, config)
441-
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
442-
self.entity_id = async_generate_entity_id(
443-
ENTITY_ID_FORMAT, object_id, hass=hass
444-
)
445442
name = self._attr_name
446443
if TYPE_CHECKING:
447444
assert name is not None

homeassistant/components/template/image.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77

88
import voluptuous as vol
99

10-
from homeassistant.components.image import DOMAIN as IMAGE_DOMAIN, ImageEntity
10+
from homeassistant.components.image import (
11+
DOMAIN as IMAGE_DOMAIN,
12+
ENTITY_ID_FORMAT,
13+
ImageEntity,
14+
)
1115
from homeassistant.config_entries import ConfigEntry
1216
from homeassistant.const import CONF_DEVICE_ID, CONF_NAME, CONF_URL, CONF_VERIFY_SSL
1317
from homeassistant.core import HomeAssistant, callback
@@ -91,6 +95,7 @@ class StateImageEntity(TemplateEntity, ImageEntity):
9195

9296
_attr_should_poll = False
9397
_attr_image_url: str | None = None
98+
_entity_id_format = ENTITY_ID_FORMAT
9499

95100
def __init__(
96101
self,
@@ -99,7 +104,7 @@ def __init__(
99104
unique_id: str | None,
100105
) -> None:
101106
"""Initialize the image."""
102-
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
107+
TemplateEntity.__init__(self, hass, config, unique_id)
103108
ImageEntity.__init__(self, hass, config[CONF_VERIFY_SSL])
104109
self._url_template = config[CONF_URL]
105110
self._attr_device_info = async_device_info_to_link_from_device_id(
@@ -135,6 +140,7 @@ class TriggerImageEntity(TriggerEntity, ImageEntity):
135140
"""Image entity based on trigger data."""
136141

137142
_attr_image_url: str | None = None
143+
_entity_id_format = ENTITY_ID_FORMAT
138144

139145
domain = IMAGE_DOMAIN
140146
extra_template_keys = (CONF_URL,)

homeassistant/components/template/light.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,12 @@
4343
from homeassistant.core import HomeAssistant, callback
4444
from homeassistant.exceptions import TemplateError
4545
from homeassistant.helpers import config_validation as cv, template
46-
from homeassistant.helpers.entity import async_generate_entity_id
4746
from homeassistant.helpers.entity_platform import AddEntitiesCallback
4847
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
4948
from homeassistant.util import color as color_util
5049

5150
from . import TriggerUpdateCoordinator
52-
from .const import CONF_OBJECT_ID, DOMAIN
51+
from .const import DOMAIN
5352
from .entity import AbstractTemplateEntity
5453
from .helpers import async_setup_template_platform
5554
from .template_entity import (
@@ -215,6 +214,8 @@ async def async_setup_platform(
215214
class AbstractTemplateLight(AbstractTemplateEntity, LightEntity):
216215
"""Representation of a template lights features."""
217216

217+
_entity_id_format = ENTITY_ID_FORMAT
218+
218219
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
219220
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
220221
def __init__( # pylint: disable=super-init-not-called
@@ -893,12 +894,8 @@ def __init__(
893894
unique_id: str | None,
894895
) -> None:
895896
"""Initialize the light."""
896-
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
897+
TemplateEntity.__init__(self, hass, config, unique_id)
897898
AbstractTemplateLight.__init__(self, config)
898-
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
899-
self.entity_id = async_generate_entity_id(
900-
ENTITY_ID_FORMAT, object_id, hass=hass
901-
)
902899
name = self._attr_name
903900
if TYPE_CHECKING:
904901
assert name is not None

homeassistant/components/template/lock.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from homeassistant.components.lock import (
1111
DOMAIN as LOCK_DOMAIN,
12+
ENTITY_ID_FORMAT,
1213
PLATFORM_SCHEMA as LOCK_PLATFORM_SCHEMA,
1314
LockEntity,
1415
LockEntityFeature,
@@ -104,6 +105,8 @@ async def async_setup_platform(
104105
class AbstractTemplateLock(AbstractTemplateEntity, LockEntity):
105106
"""Representation of a template lock features."""
106107

108+
_entity_id_format = ENTITY_ID_FORMAT
109+
107110
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
108111
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
109112
def __init__(self, config: dict[str, Any]) -> None: # pylint: disable=super-init-not-called
@@ -283,7 +286,7 @@ def __init__(
283286
unique_id: str | None,
284287
) -> None:
285288
"""Initialize the lock."""
286-
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
289+
TemplateEntity.__init__(self, hass, config, unique_id)
287290
AbstractTemplateLock.__init__(self, config)
288291
name = self._attr_name
289292
if TYPE_CHECKING:

0 commit comments

Comments
 (0)