Remove deprecated hass.components (#141947)

This commit is contained in:
Jan-Philipp Benecke
2025-04-23 14:04:36 +02:00
committed by GitHub
parent 3cb301214f
commit f22eca3d9e
5 changed files with 2 additions and 172 deletions

View File

@ -443,7 +443,6 @@ class HomeAssistant:
self.states = StateMachine(self.bus, self.loop)
self.config = Config(self, config_dir)
self.config.async_initialize()
self.components = loader.Components(self)
self.helpers = loader.Helpers(self)
self.state: CoreState = CoreState.not_running
self.exit_code: int = 0

View File

@ -1710,45 +1710,6 @@ class ModuleWrapper:
return value
class Components:
"""Helper to load components."""
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize the Components class."""
self._hass = hass
def __getattr__(self, comp_name: str) -> ModuleWrapper:
"""Fetch a component."""
# Test integration cache
integration = self._hass.data[DATA_INTEGRATIONS].get(comp_name)
if isinstance(integration, Integration):
component: ComponentProtocol | None = integration.get_component()
else:
# Fallback to importing old-school
component = _load_file(self._hass, comp_name, _lookup_path(self._hass))
if component is None:
raise ImportError(f"Unable to load {comp_name}")
# Local import to avoid circular dependencies
# pylint: disable-next=import-outside-toplevel
from .helpers.frame import ReportBehavior, report_usage
report_usage(
f"accesses hass.components.{comp_name}, which"
f" should be updated to import functions used from {comp_name} directly",
core_behavior=ReportBehavior.IGNORE,
core_integration_behavior=ReportBehavior.IGNORE,
custom_integration_behavior=ReportBehavior.LOG,
breaks_in_ha_version="2025.3",
)
wrapped = ModuleWrapper(self._hass, component)
setattr(self, comp_name, wrapped)
return wrapped
class Helpers:
"""Helper to load helpers."""

View File

@ -84,37 +84,6 @@ class ImportCollector(ast.NodeVisitor):
if name_node.name.startswith("homeassistant.components."):
self._add_reference(name_node.name.split(".")[2])
def visit_Attribute(self, node: ast.Attribute) -> None:
"""Visit Attribute node."""
# hass.components.hue.async_create()
# Name(id=hass)
# .Attribute(attr=hue)
# .Attribute(attr=async_create)
# self.hass.components.hue.async_create()
# Name(id=self)
# .Attribute(attr=hass) or .Attribute(attr=_hass)
# .Attribute(attr=hue)
# .Attribute(attr=async_create)
if (
isinstance(node.value, ast.Attribute)
and node.value.attr == "components"
and (
(
isinstance(node.value.value, ast.Name)
and node.value.value.id == "hass"
)
or (
isinstance(node.value.value, ast.Attribute)
and node.value.value.attr in ("hass", "_hass")
)
)
):
self._add_reference(node.attr)
else:
# Have it visit other kids
self.generic_visit(node)
ALLOWED_USED_COMPONENTS = {
*{platform.value for platform in Platform},

View File

@ -68,33 +68,6 @@ import homeassistant.components.renamed_absolute as hue
assert mock_collector.unfiltered_referenced == {"renamed_absolute"}
def test_hass_components_var(mock_collector) -> None:
"""Test detecting a hass_components_var reference."""
mock_collector.visit(
ast.parse(
"""
def bla(hass):
hass.components.hass_components_var.async_do_something()
"""
)
)
assert mock_collector.unfiltered_referenced == {"hass_components_var"}
def test_hass_components_class(mock_collector) -> None:
"""Test detecting a hass_components_class reference."""
mock_collector.visit(
ast.parse(
"""
class Hello:
def something(self):
self.hass.components.hass_components_class.async_yo()
"""
)
)
assert mock_collector.unfiltered_referenced == {"hass_components_class"}
def test_all_imports(mock_collector) -> None:
"""Test all imports together."""
mock_collector.visit(
@ -108,13 +81,6 @@ from homeassistant.components.subimport.smart_home import EVENT_ALEXA_SMART_HOME
from homeassistant.components.child_import_field import bla
import homeassistant.components.renamed_absolute as hue
def bla(hass):
hass.components.hass_components_var.async_do_something()
class Hello:
def something(self):
self.hass.components.hass_components_class.async_yo()
"""
)
)
@ -123,6 +89,4 @@ class Hello:
"subimport",
"child_import_field",
"renamed_absolute",
"hass_components_var",
"hass_components_class",
}

View File

@ -12,13 +12,13 @@ from awesomeversion import AwesomeVersion
import pytest
from homeassistant import loader
from homeassistant.components import http, hue
from homeassistant.components import hue
from homeassistant.components.hue import light as hue_light
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.json import json_dumps
from homeassistant.util.json import json_loads
from .common import MockModule, async_get_persistent_notifications, mock_integration
from .common import MockModule, mock_integration
async def test_circular_component_dependencies(hass: HomeAssistant) -> None:
@ -114,29 +114,6 @@ async def test_nonexistent_component_dependencies(hass: HomeAssistant) -> None:
assert result == {}
def test_component_loader(hass: HomeAssistant) -> None:
"""Test loading components."""
components = loader.Components(hass)
assert components.http.CONFIG_SCHEMA is http.CONFIG_SCHEMA
assert hass.components.http.CONFIG_SCHEMA is http.CONFIG_SCHEMA
def test_component_loader_non_existing(hass: HomeAssistant) -> None:
"""Test loading components."""
components = loader.Components(hass)
with pytest.raises(ImportError):
_ = components.non_existing
async def test_component_wrapper(hass: HomeAssistant) -> None:
"""Test component wrapper."""
components = loader.Components(hass)
components.persistent_notification.async_create("message")
notifications = async_get_persistent_notifications(hass)
assert len(notifications)
async def test_helpers_wrapper(hass: HomeAssistant) -> None:
"""Test helpers wrapper."""
helpers = loader.Helpers(hass)
@ -168,10 +145,6 @@ async def test_custom_component_name(hass: HomeAssistant) -> None:
assert int_comp.__name__ == "custom_components.test_package"
assert int_comp.__package__ == "custom_components.test_package"
comp = hass.components.test_package
assert comp.__name__ == "custom_components.test_package"
assert comp.__package__ == "custom_components.test_package"
integration = await loader.async_get_integration(hass, "test")
platform = integration.get_platform("light")
assert integration.get_platform_cached("light") is platform
@ -1349,42 +1322,6 @@ async def test_config_folder_not_in_path() -> None:
import tests.testing_config.check_config_not_in_path # noqa: F401
@pytest.mark.parametrize(
("integration_frame_path", "expected"),
[
pytest.param(
"custom_components/test_integration_frame", True, id="custom integration"
),
pytest.param(
"homeassistant/components/test_integration_frame",
False,
id="core integration",
),
pytest.param("homeassistant/test_integration_frame", False, id="core"),
],
)
@pytest.mark.usefixtures("mock_integration_frame")
async def test_hass_components_use_reported(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
expected: bool,
) -> None:
"""Test whether use of hass.components is reported."""
with (
patch(
"homeassistant.components.http.start_http_server_and_save_config",
return_value=None,
),
):
await hass.components.http.start_http_server_and_save_config(hass, [], None)
reported = (
"Detected that custom integration 'test_integration_frame'"
" accesses hass.components.http, which should be updated"
) in caplog.text
assert reported == expected
async def test_async_get_component_preloads_config_and_config_flow(
hass: HomeAssistant,
) -> None: