Update object_id to default_entity_id and consolidate common schemas (#151235)

This commit is contained in:
Petro31
2025-08-27 12:06:03 -04:00
committed by GitHub
parent 4b9594b876
commit 090c74f18e
26 changed files with 322 additions and 198 deletions

View File

@@ -47,12 +47,12 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -115,7 +115,11 @@ ALARM_CONTROL_PANEL_COMMON_SCHEMA = vol.Schema(
ALARM_CONTROL_PANEL_YAML_SCHEMA = ALARM_CONTROL_PANEL_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
).extend(
make_template_entity_common_modern_schema(
ALARM_CONTROL_PANEL_DOMAIN, DEFAULT_NAME
).schema
)
ALARM_CONTROL_PANEL_LEGACY_YAML_SCHEMA = vol.Schema(
{

View File

@@ -48,23 +48,25 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util
from . import TriggerUpdateCoordinator
from .const import CONF_AVAILABILITY_TEMPLATE
from .helpers import (
async_setup_template_entry,
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA_LEGACY,
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY,
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_COMMON_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_attributes_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
DEFAULT_NAME = "Template Binary Sensor"
CONF_DELAY_ON = "delay_on"
CONF_DELAY_OFF = "delay_off"
CONF_AUTO_OFF = "auto_off"
CONF_ATTRIBUTE_TEMPLATES = "attribute_templates"
LEGACY_FIELDS = {
CONF_FRIENDLY_NAME_TEMPLATE: CONF_NAME,
@@ -83,7 +85,9 @@ BINARY_SENSOR_COMMON_SCHEMA = vol.Schema(
)
BINARY_SENSOR_YAML_SCHEMA = BINARY_SENSOR_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_COMMON_SCHEMA.schema
make_template_entity_common_modern_attributes_schema(
BINARY_SENSOR_DOMAIN, DEFAULT_NAME
).schema
)
BINARY_SENSOR_CONFIG_ENTRY_SCHEMA = BINARY_SENSOR_COMMON_SCHEMA.extend(
@@ -97,10 +101,6 @@ BINARY_SENSOR_LEGACY_YAML_SCHEMA = vol.All(
vol.Required(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_ICON_TEMPLATE): cv.template,
vol.Optional(CONF_ENTITY_PICTURE_TEMPLATE): cv.template,
vol.Optional(CONF_AVAILABILITY_TEMPLATE): cv.template,
vol.Optional(CONF_ATTRIBUTE_TEMPLATES): vol.Schema(
{cv.string: cv.template}
),
vol.Optional(ATTR_FRIENDLY_NAME): cv.string,
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
@@ -108,7 +108,9 @@ BINARY_SENSOR_LEGACY_YAML_SCHEMA = vol.All(
vol.Optional(CONF_DELAY_OFF): vol.Any(cv.positive_time_period, cv.template),
vol.Optional(CONF_UNIQUE_ID): cv.string,
}
),
)
.extend(TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA_LEGACY.schema)
.extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY.schema),
)

View File

@@ -25,11 +25,11 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .const import CONF_PRESS, DOMAIN
from .helpers import async_setup_template_entry, async_setup_template_platform
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
_LOGGER = logging.getLogger(__name__)
@@ -41,7 +41,7 @@ BUTTON_YAML_SCHEMA = vol.Schema(
vol.Required(CONF_PRESS): cv.SCRIPT_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
}
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
).extend(make_template_entity_common_modern_schema(BUTTON_DOMAIN, DEFAULT_NAME).schema)
BUTTON_CONFIG_ENTRY_SCHEMA = vol.Schema(
{

View File

@@ -288,7 +288,7 @@ async def async_validate_config(hass: HomeAssistant, config: ConfigType) -> Conf
)
definitions.extend(
rewrite_legacy_to_modern_configs(
hass, template_config[old_key], legacy_fields
hass, new_key, template_config[old_key], legacy_fields
)
)
template_config = TemplateConfig({**template_config, new_key: definitions})

View File

@@ -1,9 +1,6 @@
"""Constants for the Template Platform Components."""
import voluptuous as vol
from homeassistant.const import CONF_ICON, CONF_NAME, CONF_UNIQUE_ID, Platform
from homeassistant.helpers import config_validation as cv
from homeassistant.const import Platform
from homeassistant.helpers.typing import ConfigType
CONF_ADVANCED_OPTIONS = "advanced_options"
@@ -11,25 +8,15 @@ CONF_ATTRIBUTE_TEMPLATES = "attribute_templates"
CONF_ATTRIBUTES = "attributes"
CONF_AVAILABILITY = "availability"
CONF_AVAILABILITY_TEMPLATE = "availability_template"
CONF_DEFAULT_ENTITY_ID = "default_entity_id"
CONF_MAX = "max"
CONF_MIN = "min"
CONF_OBJECT_ID = "object_id"
CONF_PICTURE = "picture"
CONF_PRESS = "press"
CONF_STEP = "step"
CONF_TURN_OFF = "turn_off"
CONF_TURN_ON = "turn_on"
TEMPLATE_ENTITY_BASE_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ICON): cv.template,
vol.Optional(CONF_NAME): cv.template,
vol.Optional(CONF_PICTURE): cv.template,
vol.Optional(CONF_UNIQUE_ID): cv.string,
vol.Optional(CONF_OBJECT_ID): cv.string,
}
)
DOMAIN = "template"
PLATFORM_STORAGE_KEY = "template_platforms"

View File

@@ -46,13 +46,13 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -122,7 +122,9 @@ COVER_YAML_SCHEMA = vol.All(
)
.extend(COVER_COMMON_SCHEMA.schema)
.extend(TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA)
.extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema),
.extend(
make_template_entity_common_modern_schema(COVER_DOMAIN, DEFAULT_NAME).schema
),
cv.has_at_least_one_key(OPEN_ACTION, POSITION_ACTION),
)

View File

@@ -2,6 +2,7 @@
from abc import abstractmethod
from collections.abc import Sequence
import logging
from typing import Any
from homeassistant.const import CONF_DEVICE_ID, CONF_OPTIMISTIC, CONF_STATE
@@ -12,7 +13,9 @@ from homeassistant.helpers.script import Script, _VarsType
from homeassistant.helpers.template import Template, TemplateStateFromEntityId
from homeassistant.helpers.typing import ConfigType
from .const import CONF_OBJECT_ID
from .const import CONF_DEFAULT_ENTITY_ID
_LOGGER = logging.getLogger(__name__)
class AbstractTemplateEntity(Entity):
@@ -49,7 +52,8 @@ class AbstractTemplateEntity(Entity):
optimistic is None and assumed_optimistic
)
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
if (default_entity_id := config.get(CONF_DEFAULT_ENTITY_ID)) is not None:
_, _, object_id = default_entity_id.partition(".")
self.entity_id = async_generate_entity_id(
self._entity_id_format, object_id, hass=self.hass
)

View File

@@ -31,11 +31,11 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_attributes_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -56,7 +56,9 @@ EVENT_COMMON_SCHEMA = vol.Schema(
)
EVENT_YAML_SCHEMA = EVENT_COMMON_SCHEMA.extend(
make_template_entity_common_modern_attributes_schema(DEFAULT_NAME).schema
make_template_entity_common_modern_attributes_schema(
EVENT_DOMAIN, DEFAULT_NAME
).schema
)

View File

@@ -49,13 +49,13 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY,
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -110,7 +110,7 @@ FAN_COMMON_SCHEMA = vol.Schema(
)
FAN_YAML_SCHEMA = FAN_COMMON_SCHEMA.extend(TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA).extend(
make_template_entity_common_modern_schema(DEFAULT_NAME).schema
make_template_entity_common_modern_schema(FAN_DOMAIN, DEFAULT_NAME).schema
)
FAN_LEGACY_YAML_SCHEMA = vol.All(

View File

@@ -38,7 +38,7 @@ from .const import (
CONF_ATTRIBUTES,
CONF_AVAILABILITY,
CONF_AVAILABILITY_TEMPLATE,
CONF_OBJECT_ID,
CONF_DEFAULT_ENTITY_ID,
CONF_PICTURE,
DOMAIN,
)
@@ -141,13 +141,14 @@ def rewrite_legacy_to_modern_config(
def rewrite_legacy_to_modern_configs(
hass: HomeAssistant,
domain: str,
entity_cfg: dict[str, dict],
extra_legacy_fields: dict[str, str],
) -> list[dict]:
"""Rewrite legacy configuration definitions to modern ones."""
entities = []
for object_id, entity_conf in entity_cfg.items():
entity_conf = {**entity_conf, CONF_OBJECT_ID: object_id}
entity_conf = {**entity_conf, CONF_DEFAULT_ENTITY_ID: f"{domain}.{object_id}"}
entity_conf = rewrite_legacy_to_modern_config(
hass, entity_conf, extra_legacy_fields
@@ -196,7 +197,7 @@ async def async_setup_template_platform(
if legacy_fields is not None:
if legacy_key:
configs = rewrite_legacy_to_modern_configs(
hass, config[legacy_key], legacy_fields
hass, domain, config[legacy_key], legacy_fields
)
else:
configs = [rewrite_legacy_to_modern_config(hass, config, legacy_fields)]

View File

@@ -27,11 +27,11 @@ from homeassistant.util import dt as dt_util
from . import TriggerUpdateCoordinator
from .const import CONF_PICTURE
from .helpers import async_setup_template_entry, async_setup_template_platform
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_attributes_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -45,7 +45,11 @@ IMAGE_YAML_SCHEMA = vol.Schema(
vol.Required(CONF_URL): cv.template,
vol.Optional(CONF_VERIFY_SSL, default=True): bool,
}
).extend(make_template_entity_common_modern_attributes_schema(DEFAULT_NAME).schema)
).extend(
make_template_entity_common_modern_attributes_schema(
IMAGE_DOMAIN, DEFAULT_NAME
).schema
)
IMAGE_CONFIG_ENTRY_SCHEMA = vol.Schema(

View File

@@ -59,13 +59,13 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -161,7 +161,7 @@ LIGHT_COMMON_SCHEMA = vol.Schema(
LIGHT_YAML_SCHEMA = LIGHT_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
).extend(make_template_entity_common_modern_schema(LIGHT_DOMAIN, DEFAULT_NAME).schema)
LIGHT_LEGACY_YAML_SCHEMA = vol.All(
cv.deprecated(CONF_ENTITY_ID),

View File

@@ -41,13 +41,13 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY,
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
CONF_CODE_FORMAT_TEMPLATE = "code_format_template"
@@ -75,7 +75,7 @@ LOCK_COMMON_SCHEMA = vol.Schema(
)
LOCK_YAML_SCHEMA = LOCK_COMMON_SCHEMA.extend(TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA).extend(
make_template_entity_common_modern_schema(DEFAULT_NAME).schema
make_template_entity_common_modern_schema(LOCK_DOMAIN, DEFAULT_NAME).schema
)
PLATFORM_SCHEMA = LOCK_PLATFORM_SCHEMA.extend(

View File

@@ -34,12 +34,12 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -58,11 +58,11 @@ NUMBER_COMMON_SCHEMA = vol.Schema(
vol.Optional(CONF_STEP, default=DEFAULT_STEP): cv.template,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
}
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
)
NUMBER_YAML_SCHEMA = NUMBER_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
).extend(make_template_entity_common_modern_schema(NUMBER_DOMAIN, DEFAULT_NAME).schema)
NUMBER_CONFIG_ENTRY_SCHEMA = NUMBER_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA.schema

View File

@@ -0,0 +1,109 @@
"""Shared schemas for config entry and YAML config items."""
from __future__ import annotations
import voluptuous as vol
from homeassistant.const import (
CONF_DEVICE_ID,
CONF_ENTITY_PICTURE_TEMPLATE,
CONF_ICON,
CONF_ICON_TEMPLATE,
CONF_NAME,
CONF_OPTIMISTIC,
CONF_UNIQUE_ID,
CONF_VARIABLES,
)
from homeassistant.helpers import config_validation as cv, selector
from .const import (
CONF_ATTRIBUTE_TEMPLATES,
CONF_ATTRIBUTES,
CONF_AVAILABILITY,
CONF_AVAILABILITY_TEMPLATE,
CONF_DEFAULT_ENTITY_ID,
CONF_PICTURE,
)
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA = vol.Schema(
{
vol.Optional(CONF_AVAILABILITY): cv.template,
}
)
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ATTRIBUTES): vol.Schema({cv.string: cv.template}),
}
)
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA = vol.Schema(
{
vol.Required(CONF_NAME): cv.template,
vol.Optional(CONF_DEVICE_ID): selector.DeviceSelector(),
}
).extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA.schema)
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA = {
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
}
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA_LEGACY = vol.Schema(
{
vol.Optional(CONF_ATTRIBUTE_TEMPLATES, default={}): vol.Schema(
{cv.string: cv.template}
),
}
)
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY = vol.Schema(
{
vol.Optional(CONF_AVAILABILITY_TEMPLATE): cv.template,
}
)
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY = vol.Schema(
{
vol.Optional(CONF_ENTITY_PICTURE_TEMPLATE): cv.template,
vol.Optional(CONF_ICON_TEMPLATE): cv.template,
}
).extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY.schema)
def make_template_entity_base_schema(domain: str, default_name: str) -> vol.Schema:
"""Return a schema with default name."""
return vol.Schema(
{
vol.Optional(CONF_DEFAULT_ENTITY_ID): vol.All(
cv.entity_id, cv.entity_domain(domain)
),
vol.Optional(CONF_ICON): cv.template,
vol.Optional(CONF_NAME, default=default_name): cv.template,
vol.Optional(CONF_PICTURE): cv.template,
vol.Optional(CONF_UNIQUE_ID): cv.string,
}
)
def make_template_entity_common_modern_schema(
domain: str,
default_name: str,
) -> vol.Schema:
"""Return a schema with default name."""
return vol.Schema(
{
vol.Optional(CONF_AVAILABILITY): cv.template,
vol.Optional(CONF_VARIABLES): cv.SCRIPT_VARIABLES_SCHEMA,
}
).extend(make_template_entity_base_schema(domain, default_name).schema)
def make_template_entity_common_modern_attributes_schema(
domain: str,
default_name: str,
) -> vol.Schema:
"""Return a schema with default name."""
return make_template_entity_common_modern_schema(domain, default_name).extend(
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA.schema
)

View File

@@ -32,12 +32,12 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -57,7 +57,7 @@ SELECT_COMMON_SCHEMA = vol.Schema(
SELECT_YAML_SCHEMA = SELECT_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
).extend(make_template_entity_common_modern_schema(SELECT_DOMAIN, DEFAULT_NAME).schema)
SELECT_CONFIG_ENTRY_SCHEMA = SELECT_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA.schema

View File

@@ -52,19 +52,22 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util
from . import TriggerUpdateCoordinator
from .const import CONF_ATTRIBUTE_TEMPLATES, CONF_AVAILABILITY_TEMPLATE
from .helpers import (
async_setup_template_entry,
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA_LEGACY,
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY,
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_COMMON_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_attributes_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
DEFAULT_NAME = "Template Sensor"
LEGACY_FIELDS = {
CONF_FRIENDLY_NAME_TEMPLATE: CONF_NAME,
CONF_VALUE_TEMPLATE: CONF_STATE,
@@ -100,7 +103,11 @@ SENSOR_YAML_SCHEMA = vol.All(
}
)
.extend(SENSOR_COMMON_SCHEMA.schema)
.extend(TEMPLATE_ENTITY_COMMON_SCHEMA.schema),
.extend(
make_template_entity_common_modern_attributes_schema(
SENSOR_DOMAIN, DEFAULT_NAME
).schema
),
validate_last_reset,
)
@@ -116,17 +123,15 @@ SENSOR_LEGACY_YAML_SCHEMA = vol.All(
vol.Optional(CONF_ICON_TEMPLATE): cv.template,
vol.Optional(CONF_ENTITY_PICTURE_TEMPLATE): cv.template,
vol.Optional(CONF_FRIENDLY_NAME_TEMPLATE): cv.template,
vol.Optional(CONF_AVAILABILITY_TEMPLATE): cv.template,
vol.Optional(CONF_ATTRIBUTE_TEMPLATES, default={}): vol.Schema(
{cv.string: cv.template}
),
vol.Optional(CONF_FRIENDLY_NAME): cv.string,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_UNIQUE_ID): cv.string,
}
),
)
.extend(TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA_LEGACY.schema)
.extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY.schema),
)

View File

@@ -44,13 +44,13 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_VALID_STATES = [STATE_ON, STATE_OFF, "true", "false"]
@@ -71,7 +71,7 @@ SWITCH_COMMON_SCHEMA = vol.Schema(
SWITCH_YAML_SCHEMA = SWITCH_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
).extend(make_template_entity_common_modern_schema(SWITCH_DOMAIN, DEFAULT_NAME).schema)
SWITCH_LEGACY_YAML_SCHEMA = vol.All(
cv.deprecated(ATTR_ENTITY_ID),

View File

@@ -12,12 +12,8 @@ import voluptuous as vol
from homeassistant.components.blueprint import CONF_USE_BLUEPRINT
from homeassistant.const import (
CONF_DEVICE_ID,
CONF_ENTITY_PICTURE_TEMPLATE,
CONF_ICON,
CONF_ICON_TEMPLATE,
CONF_NAME,
CONF_OPTIMISTIC,
CONF_PATH,
CONF_VARIABLES,
STATE_UNKNOWN,
@@ -32,7 +28,7 @@ from homeassistant.core import (
validate_state,
)
from homeassistant.exceptions import TemplateError
from homeassistant.helpers import config_validation as cv, selector
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import (
TrackTemplate,
@@ -47,107 +43,13 @@ from homeassistant.helpers.template import (
TemplateStateFromEntityId,
result_as_boolean,
)
from homeassistant.helpers.trigger_template_entity import (
make_template_entity_base_schema,
)
from homeassistant.helpers.typing import ConfigType
from .const import (
CONF_ATTRIBUTE_TEMPLATES,
CONF_ATTRIBUTES,
CONF_AVAILABILITY,
CONF_AVAILABILITY_TEMPLATE,
CONF_PICTURE,
TEMPLATE_ENTITY_BASE_SCHEMA,
)
from .const import CONF_ATTRIBUTES, CONF_AVAILABILITY, CONF_PICTURE
from .entity import AbstractTemplateEntity
_LOGGER = logging.getLogger(__name__)
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA = vol.Schema(
{
vol.Optional(CONF_AVAILABILITY): cv.template,
}
)
TEMPLATE_ENTITY_ICON_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ICON): cv.template,
}
)
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ATTRIBUTES): vol.Schema({cv.string: cv.template}),
}
)
TEMPLATE_ENTITY_COMMON_SCHEMA = (
vol.Schema(
{
vol.Optional(CONF_AVAILABILITY): cv.template,
vol.Optional(CONF_VARIABLES): cv.SCRIPT_VARIABLES_SCHEMA,
}
)
.extend(TEMPLATE_ENTITY_BASE_SCHEMA.schema)
.extend(TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA.schema)
)
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA = vol.Schema(
{
vol.Required(CONF_NAME): cv.template,
vol.Optional(CONF_DEVICE_ID): selector.DeviceSelector(),
}
).extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA.schema)
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA = {
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
}
def make_template_entity_common_modern_schema(
default_name: str,
) -> vol.Schema:
"""Return a schema with default name."""
return vol.Schema(
{
vol.Optional(CONF_AVAILABILITY): cv.template,
vol.Optional(CONF_VARIABLES): cv.SCRIPT_VARIABLES_SCHEMA,
}
).extend(make_template_entity_base_schema(default_name).schema)
def make_template_entity_common_modern_attributes_schema(
default_name: str,
) -> vol.Schema:
"""Return a schema with default name."""
return make_template_entity_common_modern_schema(default_name).extend(
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA.schema
)
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA_LEGACY = vol.Schema(
{
vol.Optional(CONF_ATTRIBUTE_TEMPLATES, default={}): vol.Schema(
{cv.string: cv.template}
),
}
)
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY = vol.Schema(
{
vol.Optional(CONF_AVAILABILITY_TEMPLATE): cv.template,
}
)
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY = vol.Schema(
{
vol.Optional(CONF_ENTITY_PICTURE_TEMPLATE): cv.template,
vol.Optional(CONF_ICON_TEMPLATE): cv.template,
}
).extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY.schema)
class _TemplateAttribute:
"""Attribute value linked to template result."""

View File

@@ -41,11 +41,11 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -83,7 +83,7 @@ UPDATE_COMMON_SCHEMA = vol.Schema(
)
UPDATE_YAML_SCHEMA = UPDATE_COMMON_SCHEMA.extend(
make_template_entity_common_modern_schema(DEFAULT_NAME).schema
make_template_entity_common_modern_schema(UPDATE_DOMAIN, DEFAULT_NAME).schema
)
UPDATE_CONFIG_ENTRY_SCHEMA = UPDATE_COMMON_SCHEMA.extend(

View File

@@ -54,14 +54,14 @@ from .helpers import (
async_setup_template_platform,
async_setup_template_preview,
)
from .template_entity import (
from .schemas import (
TEMPLATE_ENTITY_ATTRIBUTES_SCHEMA_LEGACY,
TEMPLATE_ENTITY_AVAILABILITY_SCHEMA_LEGACY,
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
TemplateEntity,
make_template_entity_common_modern_attributes_schema,
)
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
_LOGGER = logging.getLogger(__name__)
@@ -109,7 +109,11 @@ VACUUM_COMMON_SCHEMA = vol.Schema(
VACUUM_YAML_SCHEMA = VACUUM_COMMON_SCHEMA.extend(
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA
).extend(make_template_entity_common_modern_attributes_schema(DEFAULT_NAME).schema)
).extend(
make_template_entity_common_modern_attributes_schema(
VACUUM_DOMAIN, DEFAULT_NAME
).schema
)
VACUUM_LEGACY_YAML_SCHEMA = vol.All(
cv.deprecated(CONF_ENTITY_ID),

View File

@@ -53,7 +53,8 @@ from homeassistant.util.unit_conversion import (
from .coordinator import TriggerUpdateCoordinator
from .helpers import async_setup_template_platform
from .template_entity import TemplateEntity, make_template_entity_common_modern_schema
from .schemas import make_template_entity_common_modern_schema
from .template_entity import TemplateEntity
from .trigger_entity import TriggerEntity
CHECK_FORECAST_KEYS = (
@@ -132,7 +133,7 @@ WEATHER_YAML_SCHEMA = vol.Schema(
vol.Optional(CONF_WIND_SPEED_TEMPLATE): cv.template,
vol.Optional(CONF_WIND_SPEED_UNIT): vol.In(SpeedConverter.VALID_UNITS),
}
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
).extend(make_template_entity_common_modern_schema(WEATHER_DOMAIN, DEFAULT_NAME).schema)
PLATFORM_SCHEMA = vol.Schema(
{

View File

@@ -7,6 +7,7 @@ import voluptuous as vol
from homeassistant.components.template.config import CONFIG_SECTION_SCHEMA
from homeassistant.core import HomeAssistant
from homeassistant.helpers.template import Template
@pytest.mark.parametrize(
@@ -48,3 +49,47 @@ async def test_invalid_schema(hass: HomeAssistant, config: dict) -> None:
"""Test invalid config schemas."""
with pytest.raises(vol.Invalid):
CONFIG_SECTION_SCHEMA(config)
async def test_valid_default_entity_id(hass: HomeAssistant) -> None:
"""Test valid default_entity_id schemas."""
config = {
"button": {
"press": [],
"default_entity_id": "button.test",
},
}
assert CONFIG_SECTION_SCHEMA(config) == {
"button": [
{
"press": [],
"name": Template("Template Button", hass),
"default_entity_id": "button.test",
}
]
}
@pytest.mark.parametrize(
"default_entity_id",
[
"foo",
"{{ 'my_template' }}",
"SJLIVan as dfkaj;heafha faass00",
48,
None,
"bttn.test",
],
)
async def test_invalid_default_entity_id(
hass: HomeAssistant, default_entity_id: dict
) -> None:
"""Test invalid default_entity_id schemas."""
config = {
"button": {
"press": [],
"default_entity_id": default_entity_id,
},
}
with pytest.raises(vol.Invalid):
CONFIG_SECTION_SCHEMA(config)

View File

@@ -78,177 +78,206 @@ async def test_legacy_to_modern_config(
@pytest.mark.parametrize(
("legacy_fields", "old_attr", "new_attr", "attr_template"),
("domain", "legacy_fields", "old_attr", "new_attr", "attr_template"),
[
(
"alarm_control_panel",
ALARM_CONTROL_PANEL_LEGACY_FIELDS,
"value_template",
"state",
"{{ 1 == 1 }}",
),
(
"binary_sensor",
BINARY_SENSOR_LEGACY_FIELDS,
"value_template",
"state",
"{{ 1 == 1 }}",
),
(
"cover",
COVER_LEGACY_FIELDS,
"value_template",
"state",
"{{ 1 == 1 }}",
),
(
"cover",
COVER_LEGACY_FIELDS,
"position_template",
"position",
"{{ 100 }}",
),
(
"cover",
COVER_LEGACY_FIELDS,
"tilt_template",
"tilt",
"{{ 100 }}",
),
(
"fan",
FAN_LEGACY_FIELDS,
"value_template",
"state",
"{{ 1 == 1 }}",
),
(
"fan",
FAN_LEGACY_FIELDS,
"direction_template",
"direction",
"{{ 1 == 1 }}",
),
(
"fan",
FAN_LEGACY_FIELDS,
"oscillating_template",
"oscillating",
"{{ True }}",
),
(
"fan",
FAN_LEGACY_FIELDS,
"percentage_template",
"percentage",
"{{ 100 }}",
),
(
"fan",
FAN_LEGACY_FIELDS,
"preset_mode_template",
"preset_mode",
"{{ 'foo' }}",
),
(
"fan",
LIGHT_LEGACY_FIELDS,
"value_template",
"state",
"{{ 1 == 1 }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"rgb_template",
"rgb",
"{{ (255,255,255) }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"rgbw_template",
"rgbw",
"{{ (255,255,255,255) }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"rgbww_template",
"rgbww",
"{{ (255,255,255,255,255) }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"effect_list_template",
"effect_list",
"{{ ['a', 'b'] }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"effect_template",
"effect",
"{{ 'a' }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"level_template",
"level",
"{{ 255 }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"max_mireds_template",
"max_mireds",
"{{ 255 }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"min_mireds_template",
"min_mireds",
"{{ 255 }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"supports_transition_template",
"supports_transition",
"{{ True }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"temperature_template",
"temperature",
"{{ 255 }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"white_value_template",
"white_value",
"{{ 255 }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"hs_template",
"hs",
"{{ (255, 255) }}",
),
(
"light",
LIGHT_LEGACY_FIELDS,
"color_template",
"hs",
"{{ (255, 255) }}",
),
(
"sensor",
SENSOR_LEGACY_FIELDS,
"value_template",
"state",
"{{ 1 == 1 }}",
),
(
"sensor",
SWITCH_LEGACY_FIELDS,
"value_template",
"state",
"{{ 1 == 1 }}",
),
(
"vacuum",
VACUUM_LEGACY_FIELDS,
"value_template",
"state",
"{{ 1 == 1 }}",
),
(
"vacuum",
VACUUM_LEGACY_FIELDS,
"battery_level_template",
"battery_level",
"{{ 100 }}",
),
(
"vacuum",
VACUUM_LEGACY_FIELDS,
"fan_speed_template",
"fan_speed",
@@ -258,6 +287,7 @@ async def test_legacy_to_modern_config(
)
async def test_legacy_to_modern_configs(
hass: HomeAssistant,
domain: str,
legacy_fields,
old_attr: str,
new_attr: str,
@@ -274,7 +304,9 @@ async def test_legacy_to_modern_configs(
old_attr: attr_template,
}
}
altered_configs = rewrite_legacy_to_modern_configs(hass, config, legacy_fields)
altered_configs = rewrite_legacy_to_modern_configs(
hass, domain, config, legacy_fields
)
assert len(altered_configs) == 1
@@ -283,7 +315,7 @@ async def test_legacy_to_modern_configs(
"availability": Template("{{ 1 == 1 }}", hass),
"icon": Template("{{ 'mdi.abc' }}", hass),
"name": Template("foo bar", hass),
"object_id": "foo",
"default_entity_id": f"{domain}.foo",
"picture": Template("{{ 'mypicture.jpg' }}", hass),
"unique_id": "foo-bar-entity",
new_attr: Template(attr_template, hass),
@@ -292,14 +324,15 @@ async def test_legacy_to_modern_configs(
@pytest.mark.parametrize(
"legacy_fields",
("domain", "legacy_fields"),
[
BINARY_SENSOR_LEGACY_FIELDS,
SENSOR_LEGACY_FIELDS,
("binary_sensor", BINARY_SENSOR_LEGACY_FIELDS),
("sensor", SENSOR_LEGACY_FIELDS),
],
)
async def test_friendly_name_template_legacy_to_modern_configs(
hass: HomeAssistant,
domain: str,
legacy_fields,
) -> None:
"""Test the conversion of friendly_name_tempalte in legacy template to modern template."""
@@ -312,7 +345,9 @@ async def test_friendly_name_template_legacy_to_modern_configs(
"friendly_name_template": "{{ 'foo bar' }}",
}
}
altered_configs = rewrite_legacy_to_modern_configs(hass, config, legacy_fields)
altered_configs = rewrite_legacy_to_modern_configs(
hass, domain, config, legacy_fields
)
assert len(altered_configs) == 1
@@ -320,7 +355,7 @@ async def test_friendly_name_template_legacy_to_modern_configs(
{
"availability": Template("{{ 1 == 1 }}", hass),
"icon": Template("{{ 'mdi.abc' }}", hass),
"object_id": "foo",
"default_entity_id": f"{domain}.foo",
"picture": Template("{{ 'mypicture.jpg' }}", hass),
"unique_id": "foo-bar-entity",
"name": Template("{{ 'foo bar' }}", hass),

View File

@@ -20,11 +20,21 @@ async def test_template_entity_requires_hass_set(hass: HomeAssistant) -> None:
assert len(entity._template_attrs.get(tpl_with_hass, [])) == 1
async def test_object_id(hass: HomeAssistant) -> None:
"""Test template entity creates suggested entity_id from the object_id."""
async def test_default_entity_id(hass: HomeAssistant) -> None:
"""Test template entity creates suggested entity_id from the default_entity_id."""
class TemplateTest(template_entity.TemplateEntity):
_entity_id_format = "test.{}"
entity = TemplateTest(hass, {"object_id": "test"}, "a")
entity = TemplateTest(hass, {"default_entity_id": "test.test"}, "a")
assert entity.entity_id == "test.test"
async def test_bad_default_entity_id(hass: HomeAssistant) -> None:
"""Test template entity creates suggested entity_id from the default_entity_id."""
class TemplateTest(template_entity.TemplateEntity):
_entity_id_format = "test.{}"
entity = TemplateTest(hass, {"default_entity_id": "bad.test"}, "a")
assert entity.entity_id == "test.test"

View File

@@ -137,8 +137,15 @@ async def test_script_variables_from_coordinator(hass: HomeAssistant) -> None:
assert entity._render_script_variables() == {"value": STATE_ON}
async def test_object_id(hass: HomeAssistant) -> None:
"""Test template entity creates suggested entity_id from the object_id."""
async def test_default_entity_id(hass: HomeAssistant) -> None:
"""Test template entity creates suggested entity_id from the default_entity_id."""
coordinator = TriggerUpdateCoordinator(hass, {})
entity = TestEntity(hass, coordinator, {"object_id": "test"})
entity = TestEntity(hass, coordinator, {"default_entity_id": "test.test"})
assert entity.entity_id == "test.test"
async def test_bad_default_entity_id(hass: HomeAssistant) -> None:
"""Test template entity creates suggested entity_id from the default_entity_id."""
coordinator = TriggerUpdateCoordinator(hass, {})
entity = TestEntity(hass, coordinator, {"default_entity_id": "bad.test"})
assert entity.entity_id == "test.test"