Speed up validate_entity_id (#32137)

* Speed up validate_entity_id

* Add some more invalid entity IDs

* Adjust regular expression

* Extend and sort test cases

* Update regular expression, more cases, faster

* Adjust tests, allow start with number, disallow double underscore

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
Paulus Schoutsen 2020-02-24 08:35:02 -08:00 committed by GitHub
parent 15b4975681
commit 07fa844c43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 2 deletions

View File

@ -12,6 +12,7 @@ import functools
import logging
import os
import pathlib
import re
import threading
from time import monotonic
from types import MappingProxyType
@ -63,7 +64,7 @@ from homeassistant.exceptions import (
ServiceNotFound,
Unauthorized,
)
from homeassistant.util import location, slugify
from homeassistant.util import location
from homeassistant.util.async_ import fire_coroutine_threadsafe, run_callback_threadsafe
import homeassistant.util.dt as dt_util
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM, UnitSystem
@ -103,12 +104,15 @@ def split_entity_id(entity_id: str) -> List[str]:
return entity_id.split(".", 1)
VALID_ENTITY_ID = re.compile(r"^(?!.+__)(?!_)[\da-z_]+(?<!_)\.(?!_)[\da-z_]+(?<!_)$")
def valid_entity_id(entity_id: str) -> bool:
"""Test if an entity ID is a valid format.
Format: <domain>.<entity> where both are slugs.
"""
return "." in entity_id and slugify(entity_id) == entity_id.replace(".", "_", 1)
return VALID_ENTITY_ID.match(entity_id) is not None
def valid_state(state: str) -> bool:

View File

@ -185,3 +185,12 @@ def _logbook_filtering(hass, last_changed, last_updated):
list(logbook.humanify(None, yield_events(event)))
return timer() - start
@benchmark
async def valid_entity_id(hass):
"""Run valid entity ID a million times."""
start = timer()
for _ in range(10 ** 6):
core.valid_entity_id("light.kitchen")
return timer() - start

View File

@ -1206,3 +1206,34 @@ async def test_async_functions_with_callback(hass):
await hass.services.async_call("test_domain", "test_service", blocking=True)
assert len(runs) == 3
def test_valid_entity_id():
"""Test valid entity ID."""
for invalid in [
"_light.kitchen",
".kitchen",
".light.kitchen",
"light_.kitchen",
"light._kitchen",
"light.",
"light.kitchen__ceiling",
"light.kitchen_yo_",
"light.kitchen.",
"Light.kitchen",
"light.Kitchen",
"lightkitchen",
]:
assert not ha.valid_entity_id(invalid), invalid
for valid in [
"1.a",
"1light.kitchen",
"a.1",
"a.a",
"input_boolean.hello_world_0123",
"light.1kitchen",
"light.kitchen",
"light.something_yoo",
]:
assert ha.valid_entity_id(valid), valid