Mark custom components that overwrite core (#127937)

This commit is contained in:
Petar Petrov 2024-10-16 10:28:19 +03:00 committed by GitHub
parent 5d590bc2cf
commit 1ff1b82fc7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 0 deletions

View File

@ -255,6 +255,7 @@ class Manifest(TypedDict, total=False):
usb: list[dict[str, str]]
homekit: dict[str, list[str]]
is_built_in: bool
overwrites_built_in: bool
version: str
codeowners: list[str]
loggers: list[str]
@ -451,6 +452,7 @@ async def async_get_integration_descriptions(
"single_config_entry": integration.manifest.get(
"single_config_entry", False
),
"overwrites_built_in": integration.overwrites_built_in,
}
custom_flows[integration_key][integration.domain] = metadata
@ -762,6 +764,7 @@ class Integration:
self.file_path = file_path
self.manifest = manifest
manifest["is_built_in"] = self.is_built_in
manifest["overwrites_built_in"] = self.overwrites_built_in
if self.dependencies:
self._all_dependencies_resolved: bool | None = None
@ -909,6 +912,16 @@ class Integration:
"""Test if package is a built-in integration."""
return self.pkg_path.startswith(PACKAGE_BUILTIN)
@property
def overwrites_built_in(self) -> bool:
"""Return if package overwrites a built-in integration."""
if self.is_built_in:
return False
core_comp_path = (
pathlib.Path(__file__).parent / "components" / self.domain / "manifest.json"
)
return core_comp_path.is_file()
@property
def version(self) -> AwesomeVersion | None:
"""Return the version of the integration."""

View File

@ -174,6 +174,7 @@ async def test_download_diagnostics(
"dependencies": [],
"domain": "fake_integration",
"is_built_in": True,
"overwrites_built_in": False,
"name": "fake_integration",
"requirements": [],
},
@ -260,6 +261,7 @@ async def test_download_diagnostics(
"dependencies": [],
"domain": "fake_integration",
"is_built_in": True,
"overwrites_built_in": False,
"name": "fake_integration",
"requirements": [],
},

View File

@ -583,6 +583,7 @@ def test_integration_properties(hass: HomeAssistant) -> None:
assert integration.dependencies == ["test-dep"]
assert integration.requirements == ["test-req==1.0.0"]
assert integration.is_built_in is True
assert integration.overwrites_built_in is False
assert integration.version == "1.0.0"
integration = loader.Integration(
@ -597,6 +598,7 @@ def test_integration_properties(hass: HomeAssistant) -> None:
},
)
assert integration.is_built_in is False
assert integration.overwrites_built_in is True
assert integration.homekit is None
assert integration.zeroconf is None
assert integration.dhcp is None
@ -619,6 +621,7 @@ def test_integration_properties(hass: HomeAssistant) -> None:
},
)
assert integration.is_built_in is False
assert integration.overwrites_built_in is True
assert integration.homekit is None
assert integration.zeroconf == [{"type": "_hue._tcp.local.", "name": "hue*"}]
assert integration.dhcp is None
@ -828,6 +831,29 @@ async def test_get_custom_components(hass: HomeAssistant) -> None:
mock_get.assert_called_once_with(hass)
@pytest.mark.usefixtures("enable_custom_integrations")
async def test_custom_component_overwriting_core(hass: HomeAssistant) -> None:
"""Test loading a custom component that overwrites a core component."""
# First load the core 'light' component
core_light = await loader.async_get_integration(hass, "light")
assert core_light.is_built_in is True
# create a mock custom 'light' component
mock_integration(
hass,
MockModule("light", partial_manifest={"version": "1.0.0"}),
built_in=False,
)
# Try to load the 'light' component again
custom_light = await loader.async_get_integration(hass, "light")
# Assert that we got the custom component instead of the core one
assert custom_light.is_built_in is False
assert custom_light.overwrites_built_in is True
assert custom_light.version == "1.0.0"
async def test_get_config_flows(hass: HomeAssistant) -> None:
"""Verify that custom components with config_flow are available."""
test_1_integration = _get_test_integration(hass, "test_1", False)