Remove hassio from ALLOWED_USED_COMPONENTS and move some functions to helper (#127228)

* Remove hassio from ALLOWED_USED_COMPONENTS

* Move HassioServiceInfo to helpers.service_info

* Deprecate moved functions

* Add note about deprecation

* Fix tests

* Implement suggestion

* Typo

* Update pyproject.toml

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>

---------

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
Robert Resch 2024-10-30 12:43:41 +01:00 committed by GitHub
parent 8151403bf6
commit 380974eed4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 259 additions and 108 deletions

View file

@ -7,7 +7,6 @@ from typing import Any
from adguardhome import AdGuardHome, AdGuardHomeConnectionError from adguardhome import AdGuardHome, AdGuardHomeConnectionError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import ( from homeassistant.const import (
CONF_HOST, CONF_HOST,
@ -18,6 +17,7 @@ from homeassistant.const import (
CONF_VERIFY_SSL, CONF_VERIFY_SSL,
) )
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .const import DOMAIN from .const import DOMAIN

View file

@ -29,6 +29,7 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.entity_registry as er import homeassistant.helpers.entity_registry as er
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.storage import Store from homeassistant.helpers.storage import Store
from homeassistant.helpers.system_info import async_get_system_info from homeassistant.helpers.system_info import async_get_system_info
from homeassistant.loader import ( from homeassistant.loader import (
@ -136,7 +137,7 @@ class Analytics:
@property @property
def supervisor(self) -> bool: def supervisor(self) -> bool:
"""Return bool if a supervisor is present.""" """Return bool if a supervisor is present."""
return hassio.is_hassio(self.hass) return is_hassio(self.hass)
async def load(self) -> None: async def load(self) -> None:
"""Load preferences.""" """Load preferences."""

View file

@ -1,7 +1,7 @@
{ {
"domain": "analytics", "domain": "analytics",
"name": "Analytics", "name": "Analytics",
"after_dependencies": ["energy", "recorder"], "after_dependencies": ["energy", "hassio", "recorder"],
"codeowners": ["@home-assistant/core", "@ludeeus"], "codeowners": ["@home-assistant/core", "@ludeeus"],
"dependencies": ["api", "websocket_api"], "dependencies": ["api", "websocket_api"],
"documentation": "https://www.home-assistant.io/integrations/analytics", "documentation": "https://www.home-assistant.io/integrations/analytics",

View file

@ -1,8 +1,8 @@
"""The Backup integration.""" """The Backup integration."""
from homeassistant.components.hassio import is_hassio
from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from .const import DATA_MANAGER, DOMAIN, LOGGER from .const import DATA_MANAGER, DOMAIN, LOGGER

View file

@ -20,7 +20,6 @@ from pydeconz.utils import (
import voluptuous as vol import voluptuous as vol
from homeassistant.components import ssdp from homeassistant.components import ssdp
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.config_entries import ( from homeassistant.config_entries import (
SOURCE_HASSIO, SOURCE_HASSIO,
ConfigEntry, ConfigEntry,
@ -31,6 +30,7 @@ from homeassistant.config_entries import (
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import aiohttp_client from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .const import ( from .const import (
CONF_ALLOW_CLIP_SENSOR, CONF_ALLOW_CLIP_SENSOR,

View file

@ -21,7 +21,6 @@ import aiohttp
import voluptuous as vol import voluptuous as vol
from homeassistant.components import dhcp, zeroconf from homeassistant.components import dhcp, zeroconf
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.config_entries import ( from homeassistant.config_entries import (
SOURCE_REAUTH, SOURCE_REAUTH,
ConfigEntry, ConfigEntry,
@ -32,6 +31,7 @@ from homeassistant.config_entries import (
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.device_registry import format_mac from homeassistant.helpers.device_registry import format_mac
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from homeassistant.helpers.service_info.mqtt import MqttServiceInfo from homeassistant.helpers.service_info.mqtt import MqttServiceInfo
from homeassistant.util.json import json_loads_object from homeassistant.util.json import json_loads_object

View file

@ -2,10 +2,11 @@
from __future__ import annotations from __future__ import annotations
from homeassistant.components.hassio import get_os_info, is_hassio from homeassistant.components.hassio import get_os_info
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.hassio import is_hassio
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

View file

@ -5,6 +5,7 @@ from __future__ import annotations
import asyncio import asyncio
from contextlib import suppress from contextlib import suppress
from datetime import datetime from datetime import datetime
from functools import partial
import logging import logging
import os import os
import re import re
@ -38,8 +39,22 @@ from homeassistant.helpers import (
discovery_flow, discovery_flow,
) )
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.deprecation import (
DeprecatedConstant,
all_with_deprecated_constants,
check_if_deprecated_constant,
deprecated_function,
dir_with_deprecated_constants,
)
from homeassistant.helpers.event import async_call_later from homeassistant.helpers.event import async_call_later
from homeassistant.helpers.hassio import (
get_supervisor_ip as _get_supervisor_ip,
is_hassio as _is_hassio,
)
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.service_info.hassio import (
HassioServiceInfo as _HassioServiceInfo,
)
from homeassistant.helpers.storage import Store from homeassistant.helpers.storage import Store
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
@ -97,7 +112,7 @@ from .coordinator import (
get_supervisor_info, # noqa: F401 get_supervisor_info, # noqa: F401
get_supervisor_stats, # noqa: F401 get_supervisor_stats, # noqa: F401
) )
from .discovery import HassioServiceInfo, async_setup_discovery_view # noqa: F401 from .discovery import async_setup_discovery_view # noqa: F401
from .handler import ( # noqa: F401 from .handler import ( # noqa: F401
HassIO, HassIO,
HassioAPIError, HassioAPIError,
@ -117,6 +132,14 @@ from .websocket_api import async_load_websocket_api
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
get_supervisor_ip = deprecated_function(
"homeassistant.helpers.hassio.get_supervisor_ip", breaks_in_ha_version="2025.11"
)(_get_supervisor_ip)
_DEPRECATED_HassioServiceInfo = DeprecatedConstant(
_HassioServiceInfo,
"homeassistant.helpers.service_info.hassio.HassioServiceInfo",
"2025.11",
)
STORAGE_KEY = DOMAIN STORAGE_KEY = DOMAIN
STORAGE_VERSION = 1 STORAGE_VERSION = 1
@ -272,21 +295,16 @@ def hostname_from_addon_slug(addon_slug: str) -> str:
@callback @callback
@deprecated_function(
"homeassistant.helpers.hassio.is_hassio", breaks_in_ha_version="2025.11"
)
@bind_hass @bind_hass
def is_hassio(hass: HomeAssistant) -> bool: def is_hassio(hass: HomeAssistant) -> bool:
"""Return true if Hass.io is loaded. """Return true if Hass.io is loaded.
Async friendly. Async friendly.
""" """
return DOMAIN in hass.config.components return _is_hassio(hass)
@callback
def get_supervisor_ip() -> str | None:
"""Return the supervisor ip address."""
if "SUPERVISOR" not in os.environ:
return None
return os.environ["SUPERVISOR"].partition(":")[0]
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: C901 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: C901
@ -551,3 +569,11 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.pop(ADDONS_COORDINATOR, None) hass.data.pop(ADDONS_COORDINATOR, None)
return unload_ok return unload_ok
# These can be removed if no deprecated constant are in this module anymore
__getattr__ = partial(check_if_deprecated_constant, module_globals=globals())
__dir__ = partial(
dir_with_deprecated_constants, module_globals_keys=[*globals().keys()]
)
__all__ = all_with_deprecated_constants(globals())

View file

@ -3,7 +3,6 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from dataclasses import dataclass
import logging import logging
from typing import Any from typing import Any
@ -16,9 +15,9 @@ from homeassistant import config_entries
from homeassistant.components.http import HomeAssistantView from homeassistant.components.http import HomeAssistantView
from homeassistant.const import ATTR_SERVICE, EVENT_HOMEASSISTANT_START from homeassistant.const import ATTR_SERVICE, EVENT_HOMEASSISTANT_START
from homeassistant.core import Event, HomeAssistant, callback from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.data_entry_flow import BaseServiceInfo
from homeassistant.helpers import discovery_flow from homeassistant.helpers import discovery_flow
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .const import ATTR_ADDON, ATTR_UUID, DOMAIN from .const import ATTR_ADDON, ATTR_UUID, DOMAIN
from .handler import HassIO, get_supervisor_client from .handler import HassIO, get_supervisor_client
@ -26,16 +25,6 @@ from .handler import HassIO, get_supervisor_client
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@dataclass(slots=True)
class HassioServiceInfo(BaseServiceInfo):
"""Prepared info from hassio entries."""
config: dict[str, Any]
name: str
slug: str
uuid: str
@callback @callback
def async_setup_discovery_view(hass: HomeAssistant, hassio: HassIO) -> None: def async_setup_discovery_view(hass: HomeAssistant, hassio: HassIO) -> None:
"""Discovery setup.""" """Discovery setup."""

View file

@ -5,10 +5,11 @@ import logging
from awesomeversion import AwesomeVersion, AwesomeVersionStrategy from awesomeversion import AwesomeVersion, AwesomeVersionStrategy
from homeassistant.components.hassio import get_supervisor_info, is_hassio from homeassistant.components.hassio import get_supervisor_info
from homeassistant.const import __version__ from homeassistant.const import __version__
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import DOMAIN, REQUEST_TIMEOUT, UPDATE_INTERVAL from .const import DOMAIN, REQUEST_TIMEOUT, UPDATE_INTERVAL

View file

@ -1,6 +1,7 @@
{ {
"domain": "homeassistant_alerts", "domain": "homeassistant_alerts",
"name": "Home Assistant Alerts", "name": "Home Assistant Alerts",
"after_dependencies": ["hassio"],
"codeowners": ["@home-assistant/core"], "codeowners": ["@home-assistant/core"],
"config_flow": false, "config_flow": false,
"documentation": "https://www.home-assistant.io/integrations/homeassistant_alerts", "documentation": "https://www.home-assistant.io/integrations/homeassistant_alerts",

View file

@ -2,10 +2,11 @@
from __future__ import annotations from __future__ import annotations
from homeassistant.components.hassio import get_os_info, is_hassio from homeassistant.components.hassio import get_os_info
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.hassio import is_hassio
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

View file

@ -13,7 +13,6 @@ from homeassistant.components.hassio import (
HassioAPIError, HassioAPIError,
async_get_green_settings, async_get_green_settings,
async_set_green_settings, async_set_green_settings,
is_hassio,
) )
from homeassistant.config_entries import ( from homeassistant.config_entries import (
ConfigEntry, ConfigEntry,
@ -23,6 +22,7 @@ from homeassistant.config_entries import (
) )
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import selector from homeassistant.helpers import selector
from homeassistant.helpers.hassio import is_hassio
from .const import DOMAIN from .const import DOMAIN

View file

@ -14,7 +14,6 @@ from homeassistant.components.hassio import (
AddonInfo, AddonInfo,
AddonManager, AddonManager,
AddonState, AddonState,
is_hassio,
) )
from homeassistant.components.zha.repairs.wrong_silabs_firmware import ( from homeassistant.components.zha.repairs.wrong_silabs_firmware import (
probe_silabs_firmware_type, probe_silabs_firmware_type,
@ -29,6 +28,7 @@ from homeassistant.config_entries import (
) )
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.data_entry_flow import AbortFlow from homeassistant.data_entry_flow import AbortFlow
from homeassistant.helpers.hassio import is_hassio
from . import silabs_multiprotocol_addon from . import silabs_multiprotocol_addon
from .const import ZHA_DOMAIN from .const import ZHA_DOMAIN

View file

@ -1,7 +1,7 @@
{ {
"domain": "homeassistant_hardware", "domain": "homeassistant_hardware",
"name": "Home Assistant Hardware", "name": "Home Assistant Hardware",
"after_dependencies": ["zha"], "after_dependencies": ["hassio", "zha"],
"codeowners": ["@home-assistant/core"], "codeowners": ["@home-assistant/core"],
"documentation": "https://www.home-assistant.io/integrations/homeassistant_hardware", "documentation": "https://www.home-assistant.io/integrations/homeassistant_hardware",
"integration_type": "system" "integration_type": "system"

View file

@ -17,7 +17,6 @@ from homeassistant.components.hassio import (
AddonManager, AddonManager,
AddonState, AddonState,
hostname_from_addon_slug, hostname_from_addon_slug,
is_hassio,
) )
from homeassistant.config_entries import ( from homeassistant.config_entries import (
ConfigEntry, ConfigEntry,
@ -28,6 +27,7 @@ from homeassistant.config_entries import (
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import AbortFlow from homeassistant.data_entry_flow import AbortFlow
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.integration_platform import ( from homeassistant.helpers.integration_platform import (
async_process_integration_platforms, async_process_integration_platforms,
) )

View file

@ -9,9 +9,10 @@ from typing import cast
from universal_silabs_flasher.const import ApplicationType from universal_silabs_flasher.const import ApplicationType
from homeassistant.components.hassio import AddonError, AddonState, is_hassio from homeassistant.components.hassio import AddonError, AddonState
from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.singleton import singleton from homeassistant.helpers.singleton import singleton
from .const import ( from .const import (

View file

@ -4,7 +4,7 @@ from __future__ import annotations
import logging import logging
from homeassistant.components.hassio import get_os_info, is_hassio from homeassistant.components.hassio import get_os_info
from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon import ( from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon import (
check_multi_pan_addon, check_multi_pan_addon,
) )
@ -16,6 +16,7 @@ from homeassistant.config_entries import SOURCE_HARDWARE, ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
from homeassistant.helpers import discovery_flow from homeassistant.helpers import discovery_flow
from homeassistant.helpers.hassio import is_hassio
from .const import FIRMWARE, RADIO_DEVICE, ZHA_HW_DISCOVERY_DATA from .const import FIRMWARE, RADIO_DEVICE, ZHA_HW_DISCOVERY_DATA

View file

@ -27,6 +27,7 @@ from homeassistant.config import load_yaml_config_file
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.hassio import get_supervisor_ip, is_hassio
from homeassistant.util import dt as dt_util, yaml from homeassistant.util import dt as dt_util, yaml
from .const import KEY_HASS from .const import KEY_HASS
@ -149,12 +150,8 @@ async def process_wrong_login(request: Request) -> None:
request.app[KEY_FAILED_LOGIN_ATTEMPTS][remote_addr] += 1 request.app[KEY_FAILED_LOGIN_ATTEMPTS][remote_addr] += 1
# Supervisor IP should never be banned # Supervisor IP should never be banned
if "hassio" in hass.config.components: if is_hassio(hass) and str(remote_addr) == get_supervisor_ip():
# pylint: disable-next=import-outside-toplevel return
from homeassistant.components import hassio
if hassio.get_supervisor_ip() == str(remote_addr):
return
if ( if (
request.app[KEY_FAILED_LOGIN_ATTEMPTS][remote_addr] request.app[KEY_FAILED_LOGIN_ATTEMPTS][remote_addr]

View file

@ -14,8 +14,6 @@ from homeassistant.components.hassio import (
AddonInfo, AddonInfo,
AddonManager, AddonManager,
AddonState, AddonState,
HassioServiceInfo,
is_hassio,
) )
from homeassistant.components.onboarding import async_is_onboarded from homeassistant.components.onboarding import async_is_onboarded
from homeassistant.components.zeroconf import ZeroconfServiceInfo from homeassistant.components.zeroconf import ZeroconfServiceInfo
@ -25,6 +23,8 @@ from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import AbortFlow from homeassistant.data_entry_flow import AbortFlow
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import aiohttp_client from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .addon import get_addon_manager from .addon import get_addon_manager
from .const import ( from .const import (

View file

@ -1,6 +1,7 @@
{ {
"domain": "matter", "domain": "matter",
"name": "Matter (BETA)", "name": "Matter (BETA)",
"after_dependencies": ["hassio"],
"codeowners": ["@home-assistant/matter"], "codeowners": ["@home-assistant/matter"],
"config_flow": true, "config_flow": true,
"dependencies": ["websocket_api"], "dependencies": ["websocket_api"],

View file

@ -12,7 +12,6 @@ from motioneye_client.client import (
) )
import voluptuous as vol import voluptuous as vol
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.config_entries import ( from homeassistant.config_entries import (
SOURCE_REAUTH, SOURCE_REAUTH,
ConfigEntry, ConfigEntry,
@ -24,6 +23,7 @@ from homeassistant.const import CONF_URL, CONF_WEBHOOK_ID
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from homeassistant.helpers.typing import VolDictType from homeassistant.helpers.typing import VolDictType
from . import create_motioneye_client from . import create_motioneye_client

View file

@ -16,13 +16,7 @@ from cryptography.x509 import load_pem_x509_certificate
import voluptuous as vol import voluptuous as vol
from homeassistant.components.file_upload import process_uploaded_file from homeassistant.components.file_upload import process_uploaded_file
from homeassistant.components.hassio import ( from homeassistant.components.hassio import AddonError, AddonManager, AddonState
AddonError,
AddonManager,
AddonState,
HassioServiceInfo,
is_hassio,
)
from homeassistant.config_entries import ( from homeassistant.config_entries import (
ConfigEntry, ConfigEntry,
ConfigFlow, ConfigFlow,
@ -42,6 +36,7 @@ from homeassistant.const import (
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.data_entry_flow import AbortFlow from homeassistant.data_entry_flow import AbortFlow
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.json import json_dumps from homeassistant.helpers.json import json_dumps
from homeassistant.helpers.selector import ( from homeassistant.helpers.selector import (
BooleanSelector, BooleanSelector,
@ -58,6 +53,7 @@ from homeassistant.helpers.selector import (
TextSelectorConfig, TextSelectorConfig,
TextSelectorType, TextSelectorType,
) )
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from homeassistant.util.json import JSON_DECODE_EXCEPTIONS, json_loads from homeassistant.util.json import JSON_DECODE_EXCEPTIONS, json_loads
from .addon import get_addon_manager from .addon import get_addon_manager

View file

@ -1,6 +1,7 @@
{ {
"domain": "mqtt", "domain": "mqtt",
"name": "MQTT", "name": "MQTT",
"after_dependencies": ["hassio"],
"codeowners": ["@emontnemery", "@jbouwh", "@bdraco"], "codeowners": ["@emontnemery", "@jbouwh", "@bdraco"],
"config_flow": true, "config_flow": true,
"dependencies": ["file_upload", "http"], "dependencies": ["file_upload", "http"],

View file

@ -20,6 +20,7 @@ from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.components.http.view import HomeAssistantView from homeassistant.components.http.view import HomeAssistantView
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import area_registry as ar from homeassistant.helpers import area_registry as ar
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.system_info import async_get_system_info from homeassistant.helpers.system_info import async_get_system_info
from homeassistant.helpers.translation import async_get_translations from homeassistant.helpers.translation import async_get_translations
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@ -216,7 +217,7 @@ class CoreConfigOnboardingView(_BaseOnboardingView):
from homeassistant.components import hassio from homeassistant.components import hassio
if ( if (
hassio.is_hassio(hass) is_hassio(hass)
and (core_info := hassio.get_core_info(hass)) and (core_info := hassio.get_core_info(hass))
and "raspberrypi" in core_info["machine"] and "raspberrypi" in core_info["machine"]
): ):

View file

@ -13,7 +13,7 @@ from python_otbr_api.tlv_parser import MeshcopTLVType
import voluptuous as vol import voluptuous as vol
import yarl import yarl
from homeassistant.components.hassio import AddonError, AddonManager, HassioServiceInfo from homeassistant.components.hassio import AddonError, AddonManager
from homeassistant.components.homeassistant_yellow import hardware as yellow_hardware from homeassistant.components.homeassistant_yellow import hardware as yellow_hardware
from homeassistant.components.thread import async_get_preferred_dataset from homeassistant.components.thread import async_get_preferred_dataset
from homeassistant.config_entries import SOURCE_HASSIO, ConfigFlow, ConfigFlowResult from homeassistant.config_entries import SOURCE_HASSIO, ConfigFlow, ConfigFlowResult
@ -21,6 +21,7 @@ from homeassistant.const import CONF_URL
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .const import DEFAULT_CHANNEL, DOMAIN from .const import DEFAULT_CHANNEL, DOMAIN
from .util import ( from .util import (

View file

@ -2,10 +2,11 @@
from __future__ import annotations from __future__ import annotations
from homeassistant.components.hassio import get_os_info, is_hassio from homeassistant.components.hassio import get_os_info
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.hassio import is_hassio
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

View file

@ -9,7 +9,6 @@ from urllib.parse import urlparse
import rtsp_to_webrtc import rtsp_to_webrtc
import voluptuous as vol import voluptuous as vol
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.config_entries import ( from homeassistant.config_entries import (
ConfigEntry, ConfigEntry,
ConfigFlow, ConfigFlow,
@ -19,6 +18,7 @@ from homeassistant.config_entries import (
from homeassistant.const import CONF_HOST, CONF_PORT from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from . import CONF_STUN_SERVER, DATA_SERVER_URL, DOMAIN from . import CONF_STUN_SERVER, DATA_SERVER_URL, DOMAIN

View file

@ -10,11 +10,11 @@ from aiovlc.client import Client
from aiovlc.exceptions import AuthError, ConnectError from aiovlc.exceptions import AuthError, ConnectError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_PORT from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_PORT
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .const import DEFAULT_PORT, DOMAIN from .const import DEFAULT_PORT, DOMAIN

View file

@ -8,9 +8,10 @@ from urllib.parse import urlparse
import voluptuous as vol import voluptuous as vol
from homeassistant.components import hassio, zeroconf from homeassistant.components import zeroconf
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_HOST, CONF_PORT from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .const import DOMAIN from .const import DOMAIN
from .data import WyomingService from .data import WyomingService
@ -30,7 +31,7 @@ class WyomingConfigFlow(ConfigFlow, domain=DOMAIN):
VERSION = 1 VERSION = 1
_hassio_discovery: hassio.HassioServiceInfo _hassio_discovery: HassioServiceInfo
_service: WyomingService | None = None _service: WyomingService | None = None
_name: str | None = None _name: str | None = None
@ -61,7 +62,7 @@ class WyomingConfigFlow(ConfigFlow, domain=DOMAIN):
return self.async_abort(reason="no_services") return self.async_abort(reason="no_services")
async def async_step_hassio( async def async_step_hassio(
self, discovery_info: hassio.HassioServiceInfo self, discovery_info: HassioServiceInfo
) -> ConfigFlowResult: ) -> ConfigFlowResult:
"""Handle Supervisor add-on discovery.""" """Handle Supervisor add-on discovery."""
_LOGGER.debug("Supervisor discovery info: %s", discovery_info) _LOGGER.debug("Supervisor discovery info: %s", discovery_info)

View file

@ -1,7 +1,7 @@
{ {
"domain": "zha", "domain": "zha",
"name": "Zigbee Home Automation", "name": "Zigbee Home Automation",
"after_dependencies": ["onboarding", "usb"], "after_dependencies": ["hassio", "onboarding", "usb"],
"codeowners": ["@dmulcahey", "@adminiuga", "@puddly", "@TheJulianJES"], "codeowners": ["@dmulcahey", "@adminiuga", "@puddly", "@TheJulianJES"],
"config_flow": true, "config_flow": true,
"dependencies": ["file_upload"], "dependencies": ["file_upload"],

View file

@ -18,8 +18,6 @@ from homeassistant.components.hassio import (
AddonInfo, AddonInfo,
AddonManager, AddonManager,
AddonState, AddonState,
HassioServiceInfo,
is_hassio,
) )
from homeassistant.components.zeroconf import ZeroconfServiceInfo from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.config_entries import ( from homeassistant.config_entries import (
@ -39,6 +37,8 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import AbortFlow, FlowManager from homeassistant.data_entry_flow import AbortFlow, FlowManager
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from homeassistant.helpers.typing import VolDictType from homeassistant.helpers.typing import VolDictType
from . import disconnect_client from . import disconnect_client

View file

@ -1,6 +1,7 @@
{ {
"domain": "zwave_js", "domain": "zwave_js",
"name": "Z-Wave", "name": "Z-Wave",
"after_dependencies": ["hassio"],
"codeowners": ["@home-assistant/z-wave"], "codeowners": ["@home-assistant/z-wave"],
"config_flow": true, "config_flow": true,
"dependencies": ["http", "repairs", "usb", "websocket_api"], "dependencies": ["http", "repairs", "usb", "websocket_api"],

View file

@ -78,10 +78,10 @@ from .util.enum import try_parse_enum
if TYPE_CHECKING: if TYPE_CHECKING:
from .components.bluetooth import BluetoothServiceInfoBleak from .components.bluetooth import BluetoothServiceInfoBleak
from .components.dhcp import DhcpServiceInfo from .components.dhcp import DhcpServiceInfo
from .components.hassio import HassioServiceInfo
from .components.ssdp import SsdpServiceInfo from .components.ssdp import SsdpServiceInfo
from .components.usb import UsbServiceInfo from .components.usb import UsbServiceInfo
from .components.zeroconf import ZeroconfServiceInfo from .components.zeroconf import ZeroconfServiceInfo
from .helpers.service_info.hassio import HassioServiceInfo
from .helpers.service_info.mqtt import MqttServiceInfo from .helpers.service_info.mqtt import MqttServiceInfo

View file

@ -0,0 +1,22 @@
"""Hass.io helper."""
import os
from homeassistant.core import HomeAssistant, callback
@callback
def is_hassio(hass: HomeAssistant) -> bool:
"""Return true if Hass.io is loaded.
Async friendly.
"""
return "hassio" in hass.config.components
@callback
def get_supervisor_ip() -> str | None:
"""Return the supervisor ip address."""
if "SUPERVISOR" not in os.environ:
return None
return os.environ["SUPERVISOR"].partition(":")[0]

View file

@ -16,6 +16,8 @@ from homeassistant.exceptions import HomeAssistantError
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
from homeassistant.util.network import is_ip_address, is_loopback, normalize_url from homeassistant.util.network import is_ip_address, is_loopback, normalize_url
from .hassio import is_hassio
TYPE_URL_INTERNAL = "internal_url" TYPE_URL_INTERNAL = "internal_url"
TYPE_URL_EXTERNAL = "external_url" TYPE_URL_EXTERNAL = "external_url"
SUPERVISOR_NETWORK_HOST = "homeassistant" SUPERVISOR_NETWORK_HOST = "homeassistant"
@ -42,10 +44,6 @@ def get_supervisor_network_url(
hass: HomeAssistant, *, allow_ssl: bool = False hass: HomeAssistant, *, allow_ssl: bool = False
) -> str | None: ) -> str | None:
"""Get URL for home assistant within supervisor network.""" """Get URL for home assistant within supervisor network."""
# Local import to avoid circular dependencies
# pylint: disable-next=import-outside-toplevel
from homeassistant.components.hassio import is_hassio
if hass.config.api is None or not is_hassio(hass): if hass.config.api is None or not is_hassio(hass):
return None return None
@ -180,20 +178,21 @@ def get_url(
and request_host is not None and request_host is not None
and hass.config.api is not None and hass.config.api is not None
): ):
# Local import to avoid circular dependencies
# pylint: disable-next=import-outside-toplevel
from homeassistant.components.hassio import get_host_info, is_hassio
scheme = "https" if hass.config.api.use_ssl else "http" scheme = "https" if hass.config.api.use_ssl else "http"
current_url = yarl.URL.build( current_url = yarl.URL.build(
scheme=scheme, host=request_host, port=hass.config.api.port scheme=scheme, host=request_host, port=hass.config.api.port
) )
known_hostnames = ["localhost"] known_hostnames = ["localhost"]
if is_hassio(hass) and (host_info := get_host_info(hass)): if is_hassio(hass):
known_hostnames.extend( # Local import to avoid circular dependencies
[host_info["hostname"], f"{host_info['hostname']}.local"] # pylint: disable-next=import-outside-toplevel
) from homeassistant.components.hassio import get_host_info
if host_info := get_host_info(hass):
known_hostnames.extend(
[host_info["hostname"], f"{host_info['hostname']}.local"]
)
if ( if (
( (

View file

@ -0,0 +1,16 @@
"""Hassio Discovery data."""
from dataclasses import dataclass
from typing import Any
from homeassistant.data_entry_flow import BaseServiceInfo
@dataclass(slots=True)
class HassioServiceInfo(BaseServiceInfo):
"""Prepared info from hassio entries."""
config: dict[str, Any]
name: str
slug: str
uuid: str

View file

@ -14,6 +14,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
from homeassistant.util.package import is_docker_env, is_virtual_env from homeassistant.util.package import is_docker_env, is_virtual_env
from .hassio import is_hassio
from .importlib import async_import_module from .importlib import async_import_module
from .singleton import singleton from .singleton import singleton
@ -52,13 +53,13 @@ async def async_get_system_info(hass: HomeAssistant) -> dict[str, Any]:
else: else:
hassio = await async_import_module(hass, "homeassistant.components.hassio") hassio = await async_import_module(hass, "homeassistant.components.hassio")
is_hassio = hassio.is_hassio(hass) is_hassio_ = is_hassio(hass)
info_object = { info_object = {
"installation_type": "Unknown", "installation_type": "Unknown",
"version": current_version, "version": current_version,
"dev": "dev" in current_version, "dev": "dev" in current_version,
"hassio": is_hassio, "hassio": is_hassio_,
"virtualenv": is_virtual_env(), "virtualenv": is_virtual_env(),
"python_version": platform.python_version(), "python_version": platform.python_version(),
"docker": False, "docker": False,
@ -89,7 +90,7 @@ async def async_get_system_info(hass: HomeAssistant) -> dict[str, Any]:
info_object["installation_type"] = "Home Assistant Core" info_object["installation_type"] = "Home Assistant Core"
# Enrich with Supervisor information # Enrich with Supervisor information
if is_hassio: if is_hassio_:
if not (info := hassio.get_info(hass)): if not (info := hassio.get_info(hass)):
_LOGGER.warning("No Home Assistant Supervisor info available") _LOGGER.warning("No Home Assistant Supervisor info available")
info = {} info = {}

View file

@ -25,7 +25,8 @@ requires-python = ">=3.12.0"
dependencies = [ dependencies = [
"aiodns==3.2.0", "aiodns==3.2.0",
# Integrations may depend on hassio integration without listing it to # Integrations may depend on hassio integration without listing it to
# change behavior based on presence of supervisor # change behavior based on presence of supervisor. Deprecated with #127228
# Lib can be removed with 2025.11
"aiohasupervisor==0.2.0", "aiohasupervisor==0.2.0",
"aiohttp==3.10.10", "aiohttp==3.10.10",
"aiohttp_cors==0.7.0", "aiohttp_cors==0.7.0",

View file

@ -44,6 +44,15 @@ class ImportCollector(ast.NodeVisitor):
assert self._cur_fil_dir assert self._cur_fil_dir
self.referenced[self._cur_fil_dir].add(reference_domain) self.referenced[self._cur_fil_dir].add(reference_domain)
def visit_If(self, node: ast.If) -> None:
"""Visit If node."""
if isinstance(node.test, ast.Name) and node.test.id == "TYPE_CHECKING":
# Ignore TYPE_CHECKING block
return
# Have it visit other kids
self.generic_visit(node)
def visit_ImportFrom(self, node: ast.ImportFrom) -> None: def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
"""Visit ImportFrom node.""" """Visit ImportFrom node."""
if node.module is None: if node.module is None:
@ -115,7 +124,6 @@ ALLOWED_USED_COMPONENTS = {
"device_automation", "device_automation",
"frontend", "frontend",
"group", "group",
"hassio",
"homeassistant", "homeassistant",
"input_boolean", "input_boolean",
"input_button", "input_button",

View file

@ -4,7 +4,6 @@ import aiohttp
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.adguard.const import DOMAIN from homeassistant.components.adguard.const import DOMAIN
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.config_entries import SOURCE_USER from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import ( from homeassistant.const import (
CONF_HOST, CONF_HOST,
@ -17,6 +16,7 @@ from homeassistant.const import (
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.test_util.aiohttp import AiohttpClientMocker from tests.test_util.aiohttp import AiohttpClientMocker

View file

@ -76,7 +76,7 @@ async def test_no_send(
"""Test send when no preferences are defined.""" """Test send when no preferences are defined."""
analytics = Analytics(hass) analytics = Analytics(hass)
with patch( with patch(
"homeassistant.components.hassio.is_hassio", "homeassistant.components.analytics.analytics.is_hassio",
side_effect=Mock(return_value=False), side_effect=Mock(return_value=False),
): ):
assert not analytics.preferences[ATTR_BASE] assert not analytics.preferences[ATTR_BASE]
@ -97,7 +97,7 @@ async def test_load_with_supervisor_diagnostics(hass: HomeAssistant) -> None:
side_effect=Mock(return_value={"diagnostics": True}), side_effect=Mock(return_value={"diagnostics": True}),
), ),
patch( patch(
"homeassistant.components.hassio.is_hassio", "homeassistant.components.analytics.analytics.is_hassio",
side_effect=Mock(return_value=True), side_effect=Mock(return_value=True),
), ),
): ):
@ -118,7 +118,7 @@ async def test_load_with_supervisor_without_diagnostics(hass: HomeAssistant) ->
side_effect=Mock(return_value={"diagnostics": False}), side_effect=Mock(return_value={"diagnostics": False}),
), ),
patch( patch(
"homeassistant.components.hassio.is_hassio", "homeassistant.components.analytics.analytics.is_hassio",
side_effect=Mock(return_value=True), side_effect=Mock(return_value=True),
), ),
): ):
@ -219,8 +219,12 @@ async def test_send_base_with_supervisor(
side_effect=Mock(return_value={}), side_effect=Mock(return_value={}),
), ),
patch( patch(
"homeassistant.components.hassio.is_hassio", "homeassistant.components.analytics.analytics.is_hassio",
side_effect=Mock(return_value=True), side_effect=Mock(return_value=True),
) as is_hassio_mock,
patch(
"homeassistant.helpers.system_info.is_hassio",
new=is_hassio_mock,
), ),
): ):
await analytics.load() await analytics.load()
@ -314,8 +318,12 @@ async def test_send_usage_with_supervisor(
side_effect=Mock(return_value={}), side_effect=Mock(return_value={}),
), ),
patch( patch(
"homeassistant.components.hassio.is_hassio", "homeassistant.components.analytics.analytics.is_hassio",
side_effect=Mock(return_value=True), side_effect=Mock(return_value=True),
) as is_hassio_mock,
patch(
"homeassistant.helpers.system_info.is_hassio",
new=is_hassio_mock,
), ),
): ):
await analytics.send_analytics() await analytics.send_analytics()
@ -529,8 +537,12 @@ async def test_send_statistics_with_supervisor(
side_effect=Mock(return_value={}), side_effect=Mock(return_value={}),
), ),
patch( patch(
"homeassistant.components.hassio.is_hassio", "homeassistant.components.analytics.analytics.is_hassio",
side_effect=Mock(return_value=True), side_effect=Mock(return_value=True),
) as is_hassio_mock,
patch(
"homeassistant.helpers.system_info.is_hassio",
new=is_hassio_mock,
), ),
): ):
await analytics.send_analytics() await analytics.send_analytics()

View file

@ -20,12 +20,12 @@ from homeassistant.components.deconz.const import (
DOMAIN as DECONZ_DOMAIN, DOMAIN as DECONZ_DOMAIN,
HASSIO_CONFIGURATION_URL, HASSIO_CONFIGURATION_URL,
) )
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.components.ssdp import ATTR_UPNP_MANUFACTURER_URL, ATTR_UPNP_SERIAL from homeassistant.components.ssdp import ATTR_UPNP_MANUFACTURER_URL, ATTR_UPNP_SERIAL
from homeassistant.config_entries import SOURCE_HASSIO, SOURCE_SSDP, SOURCE_USER from homeassistant.config_entries import SOURCE_HASSIO, SOURCE_SSDP, SOURCE_USER
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT, CONTENT_TYPE_JSON from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT, CONTENT_TYPE_JSON
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .conftest import API_KEY, BRIDGE_ID from .conftest import API_KEY, BRIDGE_ID

View file

@ -27,10 +27,10 @@ from homeassistant.components.esphome.const import (
DEFAULT_NEW_CONFIG_ALLOW_ALLOW_SERVICE_CALLS, DEFAULT_NEW_CONFIG_ALLOW_ALLOW_SERVICE_CALLS,
DOMAIN, DOMAIN,
) )
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from homeassistant.helpers.service_info.mqtt import MqttServiceInfo from homeassistant.helpers.service_info.mqtt import MqttServiceInfo
from . import VALID_NOISE_PSK from . import VALID_NOISE_PSK

View file

@ -10,12 +10,12 @@ from aiohttp.test_utils import TestClient
import pytest import pytest
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.hassio.discovery import HassioServiceInfo
from homeassistant.components.hassio.handler import HassioAPIError from homeassistant.components.hassio.handler import HassioAPIError
from homeassistant.components.mqtt import DOMAIN as MQTT_DOMAIN from homeassistant.components.mqtt import DOMAIN as MQTT_DOMAIN
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STARTED from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STARTED
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.discovery_flow import DiscoveryKey from homeassistant.helpers.discovery_flow import DiscoveryKey
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import ( from tests.common import (

View file

@ -1,6 +1,7 @@
"""The tests for the hassio component.""" """The tests for the hassio component."""
from datetime import timedelta from datetime import timedelta
import logging
import os import os
from typing import Any from typing import Any
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
@ -11,24 +12,31 @@ import pytest
from voluptuous import Invalid from voluptuous import Invalid
from homeassistant.auth.const import GROUP_ID_ADMIN from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.components import frontend from homeassistant.components import frontend, hassio
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.components.hassio import ( from homeassistant.components.hassio import (
ADDONS_COORDINATOR, ADDONS_COORDINATOR,
DOMAIN, DOMAIN,
STORAGE_KEY, STORAGE_KEY,
get_core_info, get_core_info,
get_supervisor_ip,
hostname_from_addon_slug, hostname_from_addon_slug,
is_hassio, is_hassio as deprecated_is_hassio,
) )
from homeassistant.components.hassio.const import REQUEST_REFRESH_DELAY from homeassistant.components.hassio.const import REQUEST_REFRESH_DELAY
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, issue_registry as ir from homeassistant.helpers import device_registry as dr, issue_registry as ir
from homeassistant.helpers.hassio import is_hassio
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import (
MockConfigEntry,
async_fire_time_changed,
import_and_test_deprecated_constant,
)
from tests.test_util.aiohttp import AiohttpClientMocker from tests.test_util.aiohttp import AiohttpClientMocker
MOCK_ENVIRON = {"SUPERVISOR": "127.0.0.1", "SUPERVISOR_TOKEN": "abcdefgh"} MOCK_ENVIRON = {"SUPERVISOR": "127.0.0.1", "SUPERVISOR_TOKEN": "abcdefgh"}
@ -1085,3 +1093,62 @@ def test_hostname_from_addon_slug() -> None:
hostname_from_addon_slug("core_silabs_multiprotocol") hostname_from_addon_slug("core_silabs_multiprotocol")
== "core-silabs-multiprotocol" == "core-silabs-multiprotocol"
) )
def test_deprecated_function_is_hassio(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test calling deprecated_is_hassio function will create log entry."""
deprecated_is_hassio(hass)
assert caplog.record_tuples == [
(
"homeassistant.components.hassio",
logging.WARNING,
"is_hassio is a deprecated function which will be removed in HA Core 2025.11. Use homeassistant.helpers.hassio.is_hassio instead",
)
]
def test_deprecated_function_get_supervisor_ip(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test calling get_supervisor_ip function will create log entry."""
get_supervisor_ip()
assert caplog.record_tuples == [
(
"homeassistant.helpers.hassio",
logging.WARNING,
"get_supervisor_ip is a deprecated function which will be removed in HA Core 2025.11. Use homeassistant.helpers.hassio.get_supervisor_ip instead",
)
]
@pytest.mark.parametrize(
("constant_name", "replacement_name", "replacement"),
[
(
"HassioServiceInfo",
"homeassistant.helpers.service_info.hassio.HassioServiceInfo",
HassioServiceInfo,
),
],
)
def test_deprecated_constants(
caplog: pytest.LogCaptureFixture,
constant_name: str,
replacement_name: str,
replacement: Any,
) -> None:
"""Test deprecated automation constants."""
import_and_test_deprecated_constant(
caplog,
hassio,
constant_name,
replacement_name,
replacement,
"2025.11",
)

View file

@ -13,11 +13,11 @@ from matter_server.client.exceptions import CannotConnect, InvalidServerVersion
import pytest import pytest
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.components.matter.const import ADDON_SLUG, DOMAIN from homeassistant.components.matter.const import ADDON_SLUG, DOMAIN
from homeassistant.components.zeroconf import ZeroconfServiceInfo from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from tests.common import MockConfigEntry from tests.common import MockConfigEntry

View file

@ -9,7 +9,6 @@ from motioneye_client.client import (
) )
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.components.motioneye.const import ( from homeassistant.components.motioneye.const import (
CONF_ADMIN_PASSWORD, CONF_ADMIN_PASSWORD,
CONF_ADMIN_USERNAME, CONF_ADMIN_USERNAME,
@ -23,6 +22,7 @@ from homeassistant.components.motioneye.const import (
from homeassistant.const import CONF_URL, CONF_WEBHOOK_ID from homeassistant.const import CONF_URL, CONF_WEBHOOK_ID
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from . import TEST_URL, create_mock_motioneye_client, create_mock_motioneye_config_entry from . import TEST_URL, create_mock_motioneye_client, create_mock_motioneye_config_entry

View file

@ -15,7 +15,7 @@ import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components import mqtt from homeassistant.components import mqtt
from homeassistant.components.hassio import AddonError, HassioServiceInfo from homeassistant.components.hassio import AddonError
from homeassistant.components.mqtt.config_flow import PWD_NOT_CHANGED from homeassistant.components.mqtt.config_flow import PWD_NOT_CHANGED
from homeassistant.const import ( from homeassistant.const import (
CONF_CLIENT_ID, CONF_CLIENT_ID,
@ -26,6 +26,7 @@ from homeassistant.const import (
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.typing import MqttMockHAClientGenerator, MqttMockPahoClient from tests.typing import MqttMockHAClientGenerator, MqttMockPahoClient

View file

@ -9,22 +9,23 @@ import aiohttp
import pytest import pytest
import python_otbr_api import python_otbr_api
from homeassistant.components import hassio, otbr from homeassistant.components import otbr
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from . import DATASET_CH15, DATASET_CH16, TEST_BORDER_AGENT_ID, TEST_BORDER_AGENT_ID_2 from . import DATASET_CH15, DATASET_CH16, TEST_BORDER_AGENT_ID, TEST_BORDER_AGENT_ID_2
from tests.common import MockConfigEntry, MockModule, mock_integration from tests.common import MockConfigEntry, MockModule, mock_integration
from tests.test_util.aiohttp import AiohttpClientMocker from tests.test_util.aiohttp import AiohttpClientMocker
HASSIO_DATA = hassio.HassioServiceInfo( HASSIO_DATA = HassioServiceInfo(
config={"host": "core-silabs-multiprotocol", "port": 8081}, config={"host": "core-silabs-multiprotocol", "port": 8081},
name="Silicon Labs Multiprotocol", name="Silicon Labs Multiprotocol",
slug="otbr", slug="otbr",
uuid="12345", uuid="12345",
) )
HASSIO_DATA_2 = hassio.HassioServiceInfo( HASSIO_DATA_2 = HassioServiceInfo(
config={"host": "core-silabs-multiprotocol_2", "port": 8082}, config={"host": "core-silabs-multiprotocol_2", "port": 8082},
name="Silicon Labs Multiprotocol", name="Silicon Labs Multiprotocol",
slug="other_addon", slug="other_addon",

View file

@ -7,11 +7,11 @@ from unittest.mock import patch
import rtsp_to_webrtc import rtsp_to_webrtc
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.components.rtsp_to_webrtc import DOMAIN from homeassistant.components.rtsp_to_webrtc import DOMAIN
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from .conftest import ComponentSetup from .conftest import ComponentSetup

View file

@ -9,10 +9,10 @@ from aiovlc.exceptions import AuthError, ConnectError
import pytest import pytest
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.components.vlc_telnet.const import DOMAIN from homeassistant.components.vlc_telnet.const import DOMAIN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from tests.common import MockConfigEntry from tests.common import MockConfigEntry

View file

@ -8,11 +8,11 @@ from syrupy.assertion import SnapshotAssertion
from wyoming.info import Info from wyoming.info import Info
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.components.wyoming.const import DOMAIN from homeassistant.components.wyoming.const import DOMAIN
from homeassistant.components.zeroconf import ZeroconfServiceInfo from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from . import EMPTY_INFO, SATELLITE_INFO, STT_INFO, TTS_INFO from . import EMPTY_INFO, SATELLITE_INFO, STT_INFO, TTS_INFO

View file

@ -17,12 +17,12 @@ from zwave_js_server.version import VersionInfo
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components import usb from homeassistant.components import usb
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.components.zeroconf import ZeroconfServiceInfo from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.components.zwave_js.config_flow import SERVER_VERSION_TIMEOUT, TITLE from homeassistant.components.zwave_js.config_flow import SERVER_VERSION_TIMEOUT, TITLE
from homeassistant.components.zwave_js.const import ADDON_SLUG, DOMAIN from homeassistant.components.zwave_js.const import ADDON_SLUG, DOMAIN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from tests.common import MockConfigEntry from tests.common import MockConfigEntry

View file

@ -727,7 +727,7 @@ async def test_get_current_request_url_with_known_host(
@patch( @patch(
"homeassistant.components.hassio.is_hassio", "homeassistant.helpers.network.is_hassio",
Mock(return_value={"hostname": "homeassistant"}), Mock(return_value={"hostname": "homeassistant"}),
) )
@patch( @patch(

View file

@ -16,7 +16,6 @@ from syrupy.assertion import SnapshotAssertion
from homeassistant import config_entries, data_entry_flow, loader from homeassistant import config_entries, data_entry_flow, loader
from homeassistant.components import dhcp from homeassistant.components import dhcp
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
EVENT_COMPONENT_LOADED, EVENT_COMPONENT_LOADED,
@ -40,6 +39,7 @@ from homeassistant.helpers import entity_registry as er, issue_registry as ir
from homeassistant.helpers.discovery_flow import DiscoveryKey from homeassistant.helpers.discovery_flow import DiscoveryKey
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.json import json_dumps from homeassistant.helpers.json import json_dumps
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.setup import async_set_domains_to_be_loaded, async_setup_component from homeassistant.setup import async_set_domains_to_be_loaded, async_setup_component

View file

@ -585,7 +585,8 @@ async def test_discovery_requirements_mqtt(hass: HomeAssistant) -> None:
) as mock_process: ) as mock_process:
await async_get_integration_with_requirements(hass, "mqtt_comp") await async_get_integration_with_requirements(hass, "mqtt_comp")
assert len(mock_process.mock_calls) == 1 assert len(mock_process.mock_calls) == 2
# one for mqtt and one for hassio
assert mock_process.mock_calls[0][1][1] == mqtt.requirements assert mock_process.mock_calls[0][1][1] == mqtt.requirements