From 7cd7259992a34c0a640a0c440c69db42b2669e21 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 7 Nov 2023 15:14:09 -0600 Subject: [PATCH] Cache common version checks (#4673) * Cache common version checks We check core version quite frequently in the code, and its a bit expensive to do all the comparsions everywhere. Since its mostly the same check happening over and over we can cache it * Cache common version checks We check core version quite frequently in the code, and its a bit expensive to do all the comparsions everywhere. Since its mostly the same check happening over and over we can cache it * fix import --- supervisor/addons/model.py | 5 ++++- supervisor/api/middleware/security.py | 6 +++--- supervisor/homeassistant/api.py | 6 ++++-- supervisor/utils/__init__.py | 11 +++++++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/supervisor/addons/model.py b/supervisor/addons/model.py index a73025191..f1714eaef 100644 --- a/supervisor/addons/model.py +++ b/supervisor/addons/model.py @@ -85,6 +85,7 @@ from ..docker.const import Capabilities from ..exceptions import AddonsNotSupportedError from ..jobs.const import JOB_GROUP_ADDON from ..jobs.job_group import JobGroup +from ..utils import version_is_new_enough from .const import ATTR_BACKUP, ATTR_CODENOTARY, AddonBackupMode from .options import AddonOptions, UiOptions from .validate import RE_SERVICE, RE_VOLUME @@ -645,7 +646,9 @@ class AddonModel(JobGroup, ABC): # Home Assistant version: AwesomeVersion | None = config.get(ATTR_HOMEASSISTANT) with suppress(AwesomeVersionException, TypeError): - if self.sys_homeassistant.version < version: + if version and not version_is_new_enough( + self.sys_homeassistant.version, version + ): raise AddonsNotSupportedError( f"Add-on {self.slug} not supported on this system, requires Home Assistant version {version} or greater", logger, diff --git a/supervisor/api/middleware/security.py b/supervisor/api/middleware/security.py index fd76b6855..db4880dfe 100644 --- a/supervisor/api/middleware/security.py +++ b/supervisor/api/middleware/security.py @@ -19,6 +19,7 @@ from ...const import ( CoreState, ) from ...coresys import CoreSys, CoreSysAttributes +from ...utils import version_is_new_enough from ..utils import api_return_error, excract_supervisor_token _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -273,9 +274,8 @@ class SecurityMiddleware(CoreSysAttributes): @middleware async def core_proxy(self, request: Request, handler: RequestHandler) -> Response: """Validate user from Core API proxy.""" - if ( - request[REQUEST_FROM] != self.sys_homeassistant - or self.sys_homeassistant.version >= _CORE_VERSION + if request[REQUEST_FROM] != self.sys_homeassistant or version_is_new_enough( + self.sys_homeassistant.version, _CORE_VERSION ): return await handler(request) diff --git a/supervisor/homeassistant/api.py b/supervisor/homeassistant/api.py index 9e0728f72..00c3a8385 100644 --- a/supervisor/homeassistant/api.py +++ b/supervisor/homeassistant/api.py @@ -13,7 +13,7 @@ from ..coresys import CoreSys, CoreSysAttributes from ..exceptions import HomeAssistantAPIError, HomeAssistantAuthError from ..jobs.const import JobExecutionLimit from ..jobs.decorator import Job -from ..utils import check_port +from ..utils import check_port, version_is_new_enough from .const import LANDINGPAGE _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -152,7 +152,9 @@ class HomeAssistantAPI(CoreSysAttributes): # get_core_state is available since 2023.8.0 and preferred # since it is significantly faster than get_config because # it does not require serializing the entire config - if self.sys_homeassistant.version >= GET_CORE_STATE_MIN_VERSION: + if version_is_new_enough( + self.sys_homeassistant.version, GET_CORE_STATE_MIN_VERSION + ): data = await self.get_core_state() else: data = await self.get_config() diff --git a/supervisor/utils/__init__.py b/supervisor/utils/__init__.py index cb704648d..dc2235992 100644 --- a/supervisor/utils/__init__.py +++ b/supervisor/utils/__init__.py @@ -1,5 +1,6 @@ """Tools file for Supervisor.""" import asyncio +from functools import lru_cache from ipaddress import IPv4Address import logging import os @@ -9,6 +10,8 @@ import socket from tempfile import TemporaryDirectory from typing import Any +from awesomeversion import AwesomeVersion + _LOGGER: logging.Logger = logging.getLogger(__name__) RE_STRING: re.Pattern = re.compile(r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))") @@ -134,3 +137,11 @@ def clean_env() -> dict[str, str]: if value := os.environ.get(key): new_env[key] = value return new_env + + +@lru_cache +def version_is_new_enough( + version: AwesomeVersion, want_version: AwesomeVersion +) -> bool: + """Return True if the given version is new enough.""" + return version >= want_version