Skip to content

Commit

Permalink
Speed up validating domains in templates (#92975)
Browse files Browse the repository at this point in the history
This path gets called quite a bit since most templates
access the state via states.DOMAIN...
  • Loading branch information
bdraco committed May 12, 2023
1 parent 5a7c3aa commit 24284fe
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
12 changes: 11 additions & 1 deletion homeassistant/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,19 @@ def split_entity_id(entity_id: str) -> tuple[str, str]:
return domain, object_id


VALID_ENTITY_ID = re.compile(r"^(?!.+__)(?!_)[\da-z_]+(?<!_)\.(?!_)[\da-z_]+(?<!_)$")
_OBJECT_ID = r"(?!_)[\da-z_]+(?<!_)"
_DOMAIN = r"(?!.+__)" + _OBJECT_ID
VALID_DOMAIN = re.compile(r"^" + _DOMAIN + r"$")
VALID_ENTITY_ID = re.compile(r"^" + _DOMAIN + r"\." + _OBJECT_ID + r"$")


@functools.lru_cache(64)
def valid_domain(domain: str) -> bool:
"""Test if a domain a valid format."""
return VALID_DOMAIN.match(domain) is not None


@functools.lru_cache(64)
def valid_entity_id(entity_id: str) -> bool:
"""Test if an entity ID is a valid format.
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/helpers/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
State,
callback,
split_entity_id,
valid_domain,
valid_entity_id,
)
from homeassistant.exceptions import TemplateError
Expand Down Expand Up @@ -796,7 +797,7 @@ def __getattr__(self, name):
if name in _RESERVED_NAMES:
return None

if not valid_entity_id(f"{name}.entity"):
if not valid_domain(name):
raise TemplateError(f"Invalid domain name '{name}'")

return _domain_states(self._hass, name)
Expand Down
26 changes: 26 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,32 @@ def test_valid_entity_id() -> None:
assert ha.valid_entity_id(valid), valid


def test_valid_domain() -> None:
"""Test valid domain."""
for invalid in [
"_light",
".kitchen",
".light.kitchen",
"light_.kitchen",
"._kitchen",
"light.",
"light.kitchen__ceiling",
"light.kitchen_yo_",
"light.kitchen.",
"Light",
]:
assert not ha.valid_domain(invalid), invalid

for valid in [
"1",
"1light",
"a",
"input_boolean",
"light",
]:
assert ha.valid_domain(valid), valid


async def test_additional_data_in_core_config(
hass: HomeAssistant, hass_storage: dict[str, Any]
) -> None:
Expand Down

0 comments on commit 24284fe

Please sign in to comment.