Drop @bind_hass use from hassio component (#111522)

* Drop `@bind_hass` use from hassio component

* Add comment why we import locally

---------

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Jan-Philipp Benecke 2024-02-28 00:25:46 +01:00 committed by GitHub
parent 0e329d2572
commit 4e4345f04e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 35 additions and 51 deletions

View file

@ -41,7 +41,6 @@ from homeassistant.helpers.event import async_call_later
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.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.loader import bind_hass
from homeassistant.util.dt import now from homeassistant.util.dt import now
from .addon_manager import AddonError, AddonInfo, AddonManager, AddonState # noqa: F401 from .addon_manager import AddonError, AddonInfo, AddonManager, AddonState # noqa: F401
@ -283,7 +282,6 @@ def hostname_from_addon_slug(addon_slug: str) -> str:
@callback @callback
@bind_hass
def get_info(hass: HomeAssistant) -> dict[str, Any] | None: def get_info(hass: HomeAssistant) -> dict[str, Any] | None:
"""Return generic information from Supervisor. """Return generic information from Supervisor.
@ -293,7 +291,6 @@ def get_info(hass: HomeAssistant) -> dict[str, Any] | None:
@callback @callback
@bind_hass
def get_host_info(hass: HomeAssistant) -> dict[str, Any] | None: def get_host_info(hass: HomeAssistant) -> dict[str, Any] | None:
"""Return generic host information. """Return generic host information.
@ -303,7 +300,6 @@ def get_host_info(hass: HomeAssistant) -> dict[str, Any] | None:
@callback @callback
@bind_hass
def get_store(hass: HomeAssistant) -> dict[str, Any] | None: def get_store(hass: HomeAssistant) -> dict[str, Any] | None:
"""Return store information. """Return store information.
@ -313,7 +309,6 @@ def get_store(hass: HomeAssistant) -> dict[str, Any] | None:
@callback @callback
@bind_hass
def get_supervisor_info(hass: HomeAssistant) -> dict[str, Any] | None: def get_supervisor_info(hass: HomeAssistant) -> dict[str, Any] | None:
"""Return Supervisor information. """Return Supervisor information.
@ -323,7 +318,6 @@ def get_supervisor_info(hass: HomeAssistant) -> dict[str, Any] | None:
@callback @callback
@bind_hass
def get_addons_info(hass: HomeAssistant) -> dict[str, dict[str, Any]] | None: def get_addons_info(hass: HomeAssistant) -> dict[str, dict[str, Any]] | None:
"""Return Addons info. """Return Addons info.
@ -333,7 +327,6 @@ def get_addons_info(hass: HomeAssistant) -> dict[str, dict[str, Any]] | None:
@callback @callback
@bind_hass
def get_addons_stats(hass: HomeAssistant) -> dict[str, Any]: def get_addons_stats(hass: HomeAssistant) -> dict[str, Any]:
"""Return Addons stats. """Return Addons stats.
@ -343,7 +336,6 @@ def get_addons_stats(hass: HomeAssistant) -> dict[str, Any]:
@callback @callback
@bind_hass
def get_core_stats(hass: HomeAssistant) -> dict[str, Any]: def get_core_stats(hass: HomeAssistant) -> dict[str, Any]:
"""Return core stats. """Return core stats.
@ -353,7 +345,6 @@ def get_core_stats(hass: HomeAssistant) -> dict[str, Any]:
@callback @callback
@bind_hass
def get_supervisor_stats(hass: HomeAssistant) -> dict[str, Any]: def get_supervisor_stats(hass: HomeAssistant) -> dict[str, Any]:
"""Return supervisor stats. """Return supervisor stats.
@ -363,7 +354,6 @@ def get_supervisor_stats(hass: HomeAssistant) -> dict[str, Any]:
@callback @callback
@bind_hass
def get_addons_changelogs(hass: HomeAssistant): def get_addons_changelogs(hass: HomeAssistant):
"""Return Addons changelogs. """Return Addons changelogs.
@ -373,7 +363,6 @@ def get_addons_changelogs(hass: HomeAssistant):
@callback @callback
@bind_hass
def get_os_info(hass: HomeAssistant) -> dict[str, Any] | None: def get_os_info(hass: HomeAssistant) -> dict[str, Any] | None:
"""Return OS information. """Return OS information.
@ -383,7 +372,6 @@ def get_os_info(hass: HomeAssistant) -> dict[str, Any] | None:
@callback @callback
@bind_hass
def get_core_info(hass: HomeAssistant) -> dict[str, Any] | None: def get_core_info(hass: HomeAssistant) -> dict[str, Any] | None:
"""Return Home Assistant Core information from Supervisor. """Return Home Assistant Core information from Supervisor.
@ -393,7 +381,6 @@ def get_core_info(hass: HomeAssistant) -> dict[str, Any] | None:
@callback @callback
@bind_hass
def get_issues_info(hass: HomeAssistant) -> SupervisorIssues | None: def get_issues_info(hass: HomeAssistant) -> SupervisorIssues | None:
"""Return Supervisor issues info. """Return Supervisor issues info.
@ -403,7 +390,6 @@ def get_issues_info(hass: HomeAssistant) -> SupervisorIssues | None:
@callback @callback
@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.

View file

@ -19,7 +19,6 @@ from homeassistant.components.http import (
) )
from homeassistant.const import SERVER_PORT from homeassistant.const import SERVER_PORT
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.loader import bind_hass
from .const import ATTR_DISCOVERY, DOMAIN, X_HASS_SOURCE from .const import ATTR_DISCOVERY, DOMAIN, X_HASS_SOURCE
@ -63,7 +62,6 @@ def api_data(
return _wrapper return _wrapper
@bind_hass
async def async_get_addon_info(hass: HomeAssistant, slug: str) -> dict: async def async_get_addon_info(hass: HomeAssistant, slug: str) -> dict:
"""Return add-on info. """Return add-on info.
@ -85,7 +83,6 @@ async def async_get_addon_store_info(hass: HomeAssistant, slug: str) -> dict:
return await hassio.send_command(command, method="get") return await hassio.send_command(command, method="get")
@bind_hass
async def async_update_diagnostics(hass: HomeAssistant, diagnostics: bool) -> bool: async def async_update_diagnostics(hass: HomeAssistant, diagnostics: bool) -> bool:
"""Update Supervisor diagnostics toggle. """Update Supervisor diagnostics toggle.
@ -95,7 +92,6 @@ async def async_update_diagnostics(hass: HomeAssistant, diagnostics: bool) -> bo
return await hassio.update_diagnostics(diagnostics) return await hassio.update_diagnostics(diagnostics)
@bind_hass
@api_data @api_data
async def async_install_addon(hass: HomeAssistant, slug: str) -> dict: async def async_install_addon(hass: HomeAssistant, slug: str) -> dict:
"""Install add-on. """Install add-on.
@ -107,7 +103,6 @@ async def async_install_addon(hass: HomeAssistant, slug: str) -> dict:
return await hassio.send_command(command, timeout=None) return await hassio.send_command(command, timeout=None)
@bind_hass
@api_data @api_data
async def async_uninstall_addon(hass: HomeAssistant, slug: str) -> dict: async def async_uninstall_addon(hass: HomeAssistant, slug: str) -> dict:
"""Uninstall add-on. """Uninstall add-on.
@ -119,7 +114,6 @@ async def async_uninstall_addon(hass: HomeAssistant, slug: str) -> dict:
return await hassio.send_command(command, timeout=60) return await hassio.send_command(command, timeout=60)
@bind_hass
@api_data @api_data
async def async_update_addon( async def async_update_addon(
hass: HomeAssistant, hass: HomeAssistant,
@ -139,7 +133,6 @@ async def async_update_addon(
) )
@bind_hass
@api_data @api_data
async def async_start_addon(hass: HomeAssistant, slug: str) -> dict: async def async_start_addon(hass: HomeAssistant, slug: str) -> dict:
"""Start add-on. """Start add-on.
@ -151,7 +144,6 @@ async def async_start_addon(hass: HomeAssistant, slug: str) -> dict:
return await hassio.send_command(command, timeout=60) return await hassio.send_command(command, timeout=60)
@bind_hass
@api_data @api_data
async def async_restart_addon(hass: HomeAssistant, slug: str) -> dict: async def async_restart_addon(hass: HomeAssistant, slug: str) -> dict:
"""Restart add-on. """Restart add-on.
@ -163,7 +155,6 @@ async def async_restart_addon(hass: HomeAssistant, slug: str) -> dict:
return await hassio.send_command(command, timeout=None) return await hassio.send_command(command, timeout=None)
@bind_hass
@api_data @api_data
async def async_stop_addon(hass: HomeAssistant, slug: str) -> dict: async def async_stop_addon(hass: HomeAssistant, slug: str) -> dict:
"""Stop add-on. """Stop add-on.
@ -175,7 +166,6 @@ async def async_stop_addon(hass: HomeAssistant, slug: str) -> dict:
return await hassio.send_command(command, timeout=60) return await hassio.send_command(command, timeout=60)
@bind_hass
@api_data @api_data
async def async_set_addon_options( async def async_set_addon_options(
hass: HomeAssistant, slug: str, options: dict hass: HomeAssistant, slug: str, options: dict
@ -189,7 +179,6 @@ async def async_set_addon_options(
return await hassio.send_command(command, payload=options) return await hassio.send_command(command, payload=options)
@bind_hass
async def async_get_addon_discovery_info(hass: HomeAssistant, slug: str) -> dict | None: async def async_get_addon_discovery_info(hass: HomeAssistant, slug: str) -> dict | None:
"""Return discovery data for an add-on.""" """Return discovery data for an add-on."""
hassio: HassIO = hass.data[DOMAIN] hassio: HassIO = hass.data[DOMAIN]
@ -198,7 +187,6 @@ async def async_get_addon_discovery_info(hass: HomeAssistant, slug: str) -> dict
return next((addon for addon in discovered_addons if addon["addon"] == slug), None) return next((addon for addon in discovered_addons if addon["addon"] == slug), None)
@bind_hass
@api_data @api_data
async def async_create_backup( async def async_create_backup(
hass: HomeAssistant, payload: dict, partial: bool = False hass: HomeAssistant, payload: dict, partial: bool = False
@ -213,7 +201,6 @@ async def async_create_backup(
return await hassio.send_command(command, payload=payload, timeout=None) return await hassio.send_command(command, payload=payload, timeout=None)
@bind_hass
@api_data @api_data
async def async_update_os(hass: HomeAssistant, version: str | None = None) -> dict: async def async_update_os(hass: HomeAssistant, version: str | None = None) -> dict:
"""Update Home Assistant Operating System. """Update Home Assistant Operating System.
@ -229,7 +216,6 @@ async def async_update_os(hass: HomeAssistant, version: str | None = None) -> di
) )
@bind_hass
@api_data @api_data
async def async_update_supervisor(hass: HomeAssistant) -> dict: async def async_update_supervisor(hass: HomeAssistant) -> dict:
"""Update Home Assistant Supervisor. """Update Home Assistant Supervisor.
@ -241,7 +227,6 @@ async def async_update_supervisor(hass: HomeAssistant) -> dict:
return await hassio.send_command(command, timeout=None) return await hassio.send_command(command, timeout=None)
@bind_hass
@api_data @api_data
async def async_update_core( async def async_update_core(
hass: HomeAssistant, version: str | None = None, backup: bool = False hass: HomeAssistant, version: str | None = None, backup: bool = False
@ -259,7 +244,6 @@ async def async_update_core(
) )
@bind_hass
@_api_bool @_api_bool
async def async_apply_suggestion(hass: HomeAssistant, suggestion_uuid: str) -> dict: async def async_apply_suggestion(hass: HomeAssistant, suggestion_uuid: str) -> dict:
"""Apply a suggestion from supervisor's resolution center. """Apply a suggestion from supervisor's resolution center.

View file

@ -40,7 +40,11 @@ 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."""
if hass.config.api is None or not hass.components.hassio.is_hassio(): # 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):
return None return None
scheme = "http" scheme = "http"
@ -125,6 +129,10 @@ def get_url(
prefer_cloud: bool = False, prefer_cloud: bool = False,
) -> str: ) -> str:
"""Get a URL to this instance.""" """Get a URL to this instance."""
# Local import to avoid circular dependencies
# pylint: disable-next=import-outside-toplevel
from homeassistant.components.hassio import get_host_info, is_hassio
if require_current_request and http.current_request.get() is None: if require_current_request and http.current_request.get() is None:
raise NoURLAvailableError raise NoURLAvailableError
@ -176,8 +184,7 @@ def get_url(
) )
known_hostnames = ["localhost"] known_hostnames = ["localhost"]
if hass.components.hassio.is_hassio(): if is_hassio(hass) and (host_info := get_host_info(hass)):
host_info = hass.components.hassio.get_host_info()
known_hostnames.extend( known_hostnames.extend(
[host_info["hostname"], f"{host_info['hostname']}.local"] [host_info["hostname"], f"{host_info['hostname']}.local"]
) )

View file

@ -10,7 +10,6 @@ from typing import Any
from homeassistant.const import __version__ as current_version from homeassistant.const import __version__ as current_version
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
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
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -27,10 +26,13 @@ def is_official_image() -> bool:
cached_get_user = cache(getuser) cached_get_user = cache(getuser)
@bind_hass
async def async_get_system_info(hass: HomeAssistant) -> dict[str, Any]: async def async_get_system_info(hass: HomeAssistant) -> dict[str, Any]:
"""Return info about the system.""" """Return info about the system."""
is_hassio = hass.components.hassio.is_hassio() # Local import to avoid circular dependencies
# pylint: disable-next=import-outside-toplevel
from homeassistant.components import hassio
is_hassio = hassio.is_hassio(hass)
info_object = { info_object = {
"installation_type": "Unknown", "installation_type": "Unknown",
@ -68,11 +70,11 @@ async def async_get_system_info(hass: HomeAssistant) -> dict[str, Any]:
# Enrich with Supervisor information # Enrich with Supervisor information
if is_hassio: if is_hassio:
if not (info := hass.components.hassio.get_info()): 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 = {}
host = hass.components.hassio.get_host_info() or {} host = hassio.get_host_info(hass) or {}
info_object["supervisor"] = info.get("supervisor") info_object["supervisor"] = info.get("supervisor")
info_object["host_os"] = host.get("operating_system") info_object["host_os"] = host.get("operating_system")
info_object["docker_version"] = info.get("docker") info_object["docker_version"] = info.get("docker")

View file

@ -15,7 +15,9 @@ from homeassistant.components.hassio import (
DOMAIN, DOMAIN,
STORAGE_KEY, STORAGE_KEY,
async_get_addon_store_info, async_get_addon_store_info,
get_core_info,
hostname_from_addon_slug, hostname_from_addon_slug,
is_hassio,
) )
from homeassistant.components.hassio.const import REQUEST_REFRESH_DELAY from homeassistant.components.hassio.const import REQUEST_REFRESH_DELAY
from homeassistant.components.hassio.handler import HassioAPIError from homeassistant.components.hassio.handler import HassioAPIError
@ -246,8 +248,8 @@ async def test_setup_api_ping(
assert result assert result
assert aioclient_mock.call_count == 19 assert aioclient_mock.call_count == 19
assert hass.components.hassio.get_core_info()["version_latest"] == "1.0.0" assert get_core_info(hass)["version_latest"] == "1.0.0"
assert hass.components.hassio.is_hassio() assert is_hassio(hass)
async def test_setup_api_panel( async def test_setup_api_panel(
@ -465,7 +467,7 @@ async def test_warn_when_cannot_connect(
result = await async_setup_component(hass, "hassio", {}) result = await async_setup_component(hass, "hassio", {})
assert result assert result
assert hass.components.hassio.is_hassio() assert is_hassio(hass)
assert "Not connected with the supervisor / system too busy!" in caplog.text assert "Not connected with the supervisor / system too busy!" in caplog.text

View file

@ -32,6 +32,16 @@ def mock_current_request_mock():
yield mock_current_request yield mock_current_request
@pytest.fixture
def patch_hassio():
"""Patch the hassio component."""
with patch("homeassistant.components.hassio.is_hassio", return_value=True), patch(
"homeassistant.components.hassio.get_host_info",
return_value={"hostname": "homeassistant"},
):
yield
async def test_get_url_internal(hass: HomeAssistant) -> None: async def test_get_url_internal(hass: HomeAssistant) -> None:
"""Test getting an instance URL when the user has set an internal URL.""" """Test getting an instance URL when the user has set an internal URL."""
assert hass.config.internal_url is None assert hass.config.internal_url is None
@ -566,7 +576,7 @@ async def test_get_request_host(hass: HomeAssistant) -> None:
async def test_get_current_request_url_with_known_host( async def test_get_current_request_url_with_known_host(
hass: HomeAssistant, current_request hass: HomeAssistant, current_request, patch_hassio
) -> None: ) -> None:
"""Test getting current request URL with known hosts addresses.""" """Test getting current request URL with known hosts addresses."""
hass.config.api = Mock(use_ssl=False, port=8123, local_ip="127.0.0.1") hass.config.api = Mock(use_ssl=False, port=8123, local_ip="127.0.0.1")
@ -595,10 +605,6 @@ async def test_get_current_request_url_with_known_host(
# Ensure hostname from Supervisor is accepted transparently # Ensure hostname from Supervisor is accepted transparently
mock_component(hass, "hassio") mock_component(hass, "hassio")
hass.components.hassio.is_hassio = Mock(return_value=True)
hass.components.hassio.get_host_info = Mock(
return_value={"hostname": "homeassistant"}
)
with patch( with patch(
"homeassistant.helpers.network._get_request_host", "homeassistant.helpers.network._get_request_host",
@ -662,11 +668,8 @@ async def test_is_internal_request(hass: HomeAssistant, mock_current_request) ->
assert is_internal_request(hass), mock_current_request.return_value.url assert is_internal_request(hass), mock_current_request.return_value.url
# Test for matching against HassOS hostname # Test for matching against HassOS hostname
with patch.object( with patch("homeassistant.components.hassio.is_hassio", return_value=True), patch(
hass.components.hassio, "is_hassio", return_value=True "homeassistant.components.hassio.get_host_info",
), patch.object(
hass.components.hassio,
"get_host_info",
return_value={"hostname": "hellohost"}, return_value={"hostname": "hellohost"},
): ):
for allowed in ("hellohost", "hellohost.local"): for allowed in ("hellohost", "hellohost.local"):