From c368ffffd57bc72eeece34aa2ffe1903fc7c1ad2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 26 May 2024 01:38:46 -1000 Subject: [PATCH] Add async_get_hass_or_none (#118164) --- homeassistant/components/hassio/__init__.py | 8 ++------ homeassistant/components/number/__init__.py | 16 ++++++++++------ homeassistant/core.py | 10 +++++++++- homeassistant/helpers/config_validation.py | 14 +++----------- homeassistant/helpers/deprecation.py | 9 ++------- homeassistant/helpers/frame.py | 8 ++------ homeassistant/util/loop.py | 9 ++------- 7 files changed, 30 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/hassio/__init__.py b/homeassistant/components/hassio/__init__.py index e4a2bfa4cce..6a084688e99 100644 --- a/homeassistant/components/hassio/__init__.py +++ b/homeassistant/components/hassio/__init__.py @@ -27,10 +27,9 @@ from homeassistant.core import ( HassJob, HomeAssistant, ServiceCall, - async_get_hass, + async_get_hass_or_none, callback, ) -from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import ( config_validation as cv, device_registry as dr, @@ -160,10 +159,7 @@ VALID_ADDON_SLUG = vol.Match(re.compile(r"^[-_.A-Za-z0-9]+$")) def valid_addon(value: Any) -> str: """Validate value is a valid addon slug.""" value = VALID_ADDON_SLUG(value) - - hass: HomeAssistant | None = None - with suppress(HomeAssistantError): - hass = async_get_hass() + hass = async_get_hass_or_none() if hass and (addons := get_addons_info(hass)) is not None and value not in addons: raise vol.Invalid("Not a valid add-on slug") diff --git a/homeassistant/components/number/__init__.py b/homeassistant/components/number/__init__.py index e5b307f5e57..77dde242b7e 100644 --- a/homeassistant/components/number/__init__.py +++ b/homeassistant/components/number/__init__.py @@ -15,8 +15,13 @@ import voluptuous as vol from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_MODE, CONF_UNIT_OF_MEASUREMENT, UnitOfTemperature -from homeassistant.core import HomeAssistant, ServiceCall, async_get_hass, callback -from homeassistant.exceptions import HomeAssistantError, ServiceValidationError +from homeassistant.core import ( + HomeAssistant, + ServiceCall, + async_get_hass_or_none, + callback, +) +from homeassistant.exceptions import ServiceValidationError from homeassistant.helpers.config_validation import ( PLATFORM_SCHEMA, PLATFORM_SCHEMA_BASE, @@ -213,10 +218,9 @@ class NumberEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_): "value", ) ): - hass: HomeAssistant | None = None - with suppress(HomeAssistantError): - hass = async_get_hass() - report_issue = async_suggest_report_issue(hass, module=cls.__module__) + report_issue = async_suggest_report_issue( + async_get_hass_or_none(), module=cls.__module__ + ) _LOGGER.warning( ( "%s::%s is overriding deprecated methods on an instance of " diff --git a/homeassistant/core.py b/homeassistant/core.py index 48a600ae1c9..9c5d8612b27 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -268,8 +268,16 @@ def async_get_hass() -> HomeAssistant: This should be used where it's very cumbersome or downright impossible to pass hass to the code which needs it. """ - if not _hass.hass: + if not (hass := async_get_hass_or_none()): raise HomeAssistantError("async_get_hass called from the wrong thread") + return hass + + +def async_get_hass_or_none() -> HomeAssistant | None: + """Return the HomeAssistant instance or None. + + Returns None when called from the wrong thread. + """ return _hass.hass diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index a7754f9aaa8..295cd13fed4 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -93,8 +93,8 @@ from homeassistant.const import ( ) from homeassistant.core import ( DOMAIN as HOMEASSISTANT_DOMAIN, - HomeAssistant, async_get_hass, + async_get_hass_or_none, split_entity_id, valid_entity_id, ) @@ -662,11 +662,7 @@ def template(value: Any | None) -> template_helper.Template: if isinstance(value, (list, dict, template_helper.Template)): raise vol.Invalid("template value should be a string") - hass: HomeAssistant | None = None - with contextlib.suppress(HomeAssistantError): - hass = async_get_hass() - - template_value = template_helper.Template(str(value), hass) + template_value = template_helper.Template(str(value), async_get_hass_or_none()) try: template_value.ensure_valid() @@ -684,11 +680,7 @@ def dynamic_template(value: Any | None) -> template_helper.Template: if not template_helper.is_template_string(str(value)): raise vol.Invalid("template value does not contain a dynamic template") - hass: HomeAssistant | None = None - with contextlib.suppress(HomeAssistantError): - hass = async_get_hass() - - template_value = template_helper.Template(str(value), hass) + template_value = template_helper.Template(str(value), async_get_hass_or_none()) try: template_value.ensure_valid() diff --git a/homeassistant/helpers/deprecation.py b/homeassistant/helpers/deprecation.py index 79dd436db95..82ff136332b 100644 --- a/homeassistant/helpers/deprecation.py +++ b/homeassistant/helpers/deprecation.py @@ -3,7 +3,6 @@ from __future__ import annotations from collections.abc import Callable -from contextlib import suppress from enum import Enum import functools import inspect @@ -167,8 +166,7 @@ def _print_deprecation_warning_internal( log_when_no_integration_is_found: bool, ) -> None: # pylint: disable=import-outside-toplevel - from homeassistant.core import HomeAssistant, async_get_hass - from homeassistant.exceptions import HomeAssistantError + from homeassistant.core import async_get_hass_or_none from homeassistant.loader import async_suggest_report_issue from .frame import MissingIntegrationFrame, get_integration_frame @@ -191,11 +189,8 @@ def _print_deprecation_warning_internal( ) else: if integration_frame.custom_integration: - hass: HomeAssistant | None = None - with suppress(HomeAssistantError): - hass = async_get_hass() report_issue = async_suggest_report_issue( - hass, + async_get_hass_or_none(), integration_domain=integration_frame.integration, module=integration_frame.module, ) diff --git a/homeassistant/helpers/frame.py b/homeassistant/helpers/frame.py index 321094ba8d9..3046b718489 100644 --- a/homeassistant/helpers/frame.py +++ b/homeassistant/helpers/frame.py @@ -4,7 +4,6 @@ from __future__ import annotations import asyncio from collections.abc import Callable -from contextlib import suppress from dataclasses import dataclass import functools from functools import cached_property @@ -14,7 +13,7 @@ import sys from types import FrameType from typing import Any, cast -from homeassistant.core import HomeAssistant, async_get_hass +from homeassistant.core import async_get_hass_or_none from homeassistant.exceptions import HomeAssistantError from homeassistant.loader import async_suggest_report_issue @@ -176,11 +175,8 @@ def _report_integration( return _REPORTED_INTEGRATIONS.add(key) - hass: HomeAssistant | None = None - with suppress(HomeAssistantError): - hass = async_get_hass() report_issue = async_suggest_report_issue( - hass, + async_get_hass_or_none(), integration_domain=integration_frame.integration, module=integration_frame.module, ) diff --git a/homeassistant/util/loop.py b/homeassistant/util/loop.py index accb63198ba..cba9f7c3900 100644 --- a/homeassistant/util/loop.py +++ b/homeassistant/util/loop.py @@ -3,15 +3,13 @@ from __future__ import annotations from collections.abc import Callable -from contextlib import suppress import functools import linecache import logging import threading from typing import Any -from homeassistant.core import HomeAssistant, async_get_hass -from homeassistant.exceptions import HomeAssistantError +from homeassistant.core import async_get_hass_or_none from homeassistant.helpers.frame import ( MissingIntegrationFrame, get_current_frame, @@ -74,11 +72,8 @@ def raise_for_blocking_call( f"https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue" ) - hass: HomeAssistant | None = None - with suppress(HomeAssistantError): - hass = async_get_hass() report_issue = async_suggest_report_issue( - hass, + async_get_hass_or_none(), integration_domain=integration_frame.integration, module=integration_frame.module, )