Move config_per_platform and extract_domain_configs to config.py (#104989)

This commit is contained in:
Erik Montnemery 2023-12-04 12:48:49 +01:00 committed by GitHub
parent 53becaa976
commit 95f7db1970
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 138 additions and 51 deletions

View file

@ -11,7 +11,7 @@ from voluptuous.humanize import humanize_error
from homeassistant.components import blueprint
from homeassistant.components.trace import TRACE_CONFIG_SCHEMA
from homeassistant.config import config_without_domain
from homeassistant.config import config_per_platform, config_without_domain
from homeassistant.const import (
CONF_ALIAS,
CONF_CONDITION,
@ -21,7 +21,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_per_platform, config_validation as cv, script
from homeassistant.helpers import config_validation as cv, script
from homeassistant.helpers.condition import async_validate_conditions_config
from homeassistant.helpers.trigger import async_validate_trigger_config
from homeassistant.helpers.typing import ConfigType

View file

@ -14,7 +14,11 @@ import voluptuous as vol
from homeassistant import util
from homeassistant.backports.functools import cached_property
from homeassistant.components import zone
from homeassistant.config import async_log_schema_error, load_yaml_config_file
from homeassistant.config import (
async_log_schema_error,
config_per_platform,
load_yaml_config_file,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_GPS_ACCURACY,
@ -33,7 +37,6 @@ from homeassistant.const import (
from homeassistant.core import Event, HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import (
config_per_platform,
config_validation as cv,
discovery,
entity_registry as er,

View file

@ -30,11 +30,7 @@ from homeassistant.core import (
callback,
)
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import (
config_per_platform,
config_validation as cv,
entity_platform,
)
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.entity_platform import AddEntitiesCallback, EntityPlatform
from homeassistant.helpers.service import (
async_extract_entity_ids,
@ -208,7 +204,7 @@ async def async_setup_platform(
await platform.async_reset()
# Extract only the config for the Home Assistant platform, ignore the rest.
for p_type, p_config in config_per_platform(conf, SCENE_DOMAIN):
for p_type, p_config in conf_util.config_per_platform(conf, SCENE_DOMAIN):
if p_type != HA_DOMAIN:
continue

View file

@ -13,13 +13,10 @@ from aiohttp.web_exceptions import HTTPNotFound
from homeassistant.components import frontend
from homeassistant.components.http import HomeAssistantView
from homeassistant.config import config_per_platform
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import (
config_per_platform,
config_validation as cv,
discovery,
)
from homeassistant.helpers import config_validation as cv, discovery
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType

View file

@ -6,10 +6,11 @@ from collections.abc import Callable, Coroutine, Mapping
from functools import partial
from typing import Any, Protocol, cast
from homeassistant.config import config_per_platform
from homeassistant.const import CONF_DESCRIPTION, CONF_NAME
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_per_platform, discovery
from homeassistant.helpers import discovery
from homeassistant.helpers.service import async_set_service_schema
from homeassistant.helpers.template import Template
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType

View file

@ -13,7 +13,7 @@ from homeassistant.components.blueprint import (
is_blueprint_instance_config,
)
from homeassistant.components.trace import TRACE_CONFIG_SCHEMA
from homeassistant.config import config_without_domain
from homeassistant.config import config_per_platform, config_without_domain
from homeassistant.const import (
CONF_ALIAS,
CONF_DEFAULT,
@ -30,7 +30,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_per_platform, config_validation as cv
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.script import (
SCRIPT_MODE_SINGLE,
async_validate_actions_config,

View file

@ -6,8 +6,9 @@ from collections.abc import AsyncIterable, Coroutine
import logging
from typing import Any
from homeassistant.config import config_per_platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_per_platform, discovery
from homeassistant.helpers import discovery
from homeassistant.helpers.typing import ConfigType
from homeassistant.setup import async_prepare_setup_platform

View file

@ -18,6 +18,7 @@ from homeassistant.components.media_player import (
SERVICE_PLAY_MEDIA,
MediaType,
)
from homeassistant.config import config_per_platform
from homeassistant.const import (
ATTR_ENTITY_ID,
CONF_DESCRIPTION,
@ -25,7 +26,7 @@ from homeassistant.const import (
CONF_PLATFORM,
)
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.helpers import config_per_platform, discovery
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.service import async_set_service_schema
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from collections import OrderedDict
from collections.abc import Callable, Sequence
from collections.abc import Callable, Iterable, Sequence
from contextlib import suppress
from dataclasses import dataclass
from enum import StrEnum
@ -48,6 +48,7 @@ from .const import (
CONF_MEDIA_DIRS,
CONF_NAME,
CONF_PACKAGES,
CONF_PLATFORM,
CONF_TEMPERATURE_UNIT,
CONF_TIME_ZONE,
CONF_TYPE,
@ -58,12 +59,7 @@ from .const import (
from .core import DOMAIN as CONF_CORE, ConfigSource, HomeAssistant, callback
from .exceptions import ConfigValidationError, HomeAssistantError
from .generated.currencies import HISTORIC_CURRENCIES
from .helpers import (
config_per_platform,
config_validation as cv,
extract_domain_configs,
issue_registry as ir,
)
from .helpers import config_validation as cv, issue_registry as ir
from .helpers.entity_values import EntityValues
from .helpers.typing import ConfigType
from .loader import ComponentProtocol, Integration, IntegrationNotFound
@ -1222,6 +1218,41 @@ def async_handle_component_errors(
)
def config_per_platform(
config: ConfigType, domain: str
) -> Iterable[tuple[str | None, ConfigType]]:
"""Break a component config into different platforms.
For example, will find 'switch', 'switch 2', 'switch 3', .. etc
Async friendly.
"""
for config_key in extract_domain_configs(config, domain):
if not (platform_config := config[config_key]):
continue
if not isinstance(platform_config, list):
platform_config = [platform_config]
item: ConfigType
platform: str | None
for item in platform_config:
try:
platform = item.get(CONF_PLATFORM)
except AttributeError:
platform = None
yield platform, item
def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]:
"""Extract keys from config for given domain name.
Async friendly.
"""
pattern = re.compile(rf"^{domain}(| .+)$")
return [key for key in config if pattern.match(key)]
async def async_process_component_config( # noqa: C901
hass: HomeAssistant,
config: ConfigType,

View file

@ -2,11 +2,8 @@
from __future__ import annotations
from collections.abc import Iterable, Sequence
import re
from typing import TYPE_CHECKING
from homeassistant.const import CONF_PLATFORM
if TYPE_CHECKING:
from .typing import ConfigType
@ -19,22 +16,23 @@ def config_per_platform(
For example, will find 'switch', 'switch 2', 'switch 3', .. etc
Async friendly.
"""
for config_key in extract_domain_configs(config, domain):
if not (platform_config := config[config_key]):
continue
# pylint: disable-next=import-outside-toplevel
from homeassistant import config as ha_config
if not isinstance(platform_config, list):
platform_config = [platform_config]
# pylint: disable-next=import-outside-toplevel
from .deprecation import _print_deprecation_warning
item: ConfigType
platform: str | None
for item in platform_config:
try:
platform = item.get(CONF_PLATFORM)
except AttributeError:
platform = None
_print_deprecation_warning(
config_per_platform,
"config.config_per_platform",
"function",
"called",
"2024.6",
)
return ha_config.config_per_platform(config, domain)
yield platform, item
config_per_platform.__name__ = "helpers.config_per_platform"
def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]:
@ -42,5 +40,20 @@ def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]:
Async friendly.
"""
pattern = re.compile(rf"^{domain}(| .+)$")
return [key for key in config if pattern.match(key)]
# pylint: disable-next=import-outside-toplevel
from homeassistant import config as ha_config
# pylint: disable-next=import-outside-toplevel
from .deprecation import _print_deprecation_warning
_print_deprecation_warning(
extract_domain_configs,
"config.extract_domain_configs",
"function",
"called",
"2024.6",
)
return ha_config.extract_domain_configs(config, domain)
extract_domain_configs.__name__ = "helpers.extract_domain_configs"

View file

@ -32,7 +32,7 @@ from homeassistant.exceptions import HomeAssistantError
from homeassistant.loader import async_get_integration, bind_hass
from homeassistant.setup import async_prepare_setup_platform
from . import config_per_platform, config_validation as cv, discovery, entity, service
from . import config_validation as cv, discovery, entity, service
from .entity_platform import EntityPlatform
from .typing import ConfigType, DiscoveryInfoType
@ -148,7 +148,7 @@ class EntityComponent(Generic[_EntityT]):
self.config = config
# Look in config for Domain, Domain 2, Domain 3 etc and load them
for p_type, p_config in config_per_platform(config, self.domain):
for p_type, p_config in conf_util.config_per_platform(config, self.domain):
if p_type is not None:
self.hass.async_create_task(
self.async_setup_platform(p_type, p_config),

View file

@ -13,7 +13,6 @@ from homeassistant.exceptions import HomeAssistantError
from homeassistant.loader import async_get_integration
from homeassistant.setup import async_setup_component
from . import config_per_platform
from .entity import Entity
from .entity_component import EntityComponent
from .entity_platform import EntityPlatform, async_get_platforms
@ -69,7 +68,7 @@ async def _resetup_platform(
root_config: dict[str, list[ConfigType]] = {platform_domain: []}
# Extract only the config for template, ignore the rest.
for p_type, p_config in config_per_platform(conf, platform_domain):
for p_type, p_config in conf_util.config_per_platform(conf, platform_domain):
if p_type != integration_domain:
continue

View file

@ -2,10 +2,12 @@
from collections import OrderedDict
import pytest
from homeassistant import helpers
def test_extract_domain_configs() -> None:
def test_extract_domain_configs(caplog: pytest.LogCaptureFixture) -> None:
"""Test the extraction of domain configuration."""
config = {
"zone": None,
@ -19,8 +21,13 @@ def test_extract_domain_configs() -> None:
helpers.extract_domain_configs(config, "zone")
)
assert (
"helpers.extract_domain_configs is a deprecated function which will be removed "
"in HA Core 2024.6. Use config.extract_domain_configs instead" in caplog.text
)
def test_config_per_platform() -> None:
def test_config_per_platform(caplog: pytest.LogCaptureFixture) -> None:
"""Test config per platform method."""
config = OrderedDict(
[
@ -36,3 +43,8 @@ def test_config_per_platform() -> None:
(None, 1),
("hello 2", config["zone Hallo"][1]),
] == list(helpers.config_per_platform(config, "zone"))
assert (
"helpers.config_per_platform is a deprecated function which will be removed "
"in HA Core 2024.6. Use config.config_per_platform instead" in caplog.text
)

View file

@ -2207,3 +2207,36 @@ async def test_yaml_error(
if record.levelno == logging.ERROR
]
assert error_records == snapshot
def test_extract_domain_configs() -> None:
"""Test the extraction of domain configuration."""
config = {
"zone": None,
"zoner": None,
"zone ": None,
"zone Hallo": None,
"zone 100": None,
}
assert {"zone", "zone Hallo", "zone 100"} == set(
config_util.extract_domain_configs(config, "zone")
)
def test_config_per_platform() -> None:
"""Test config per platform method."""
config = OrderedDict(
[
("zone", {"platform": "hello"}),
("zoner", None),
("zone Hallo", [1, {"platform": "hello 2"}]),
("zone 100", None),
]
)
assert [
("hello", config["zone"]),
(None, 1),
("hello 2", config["zone Hallo"][1]),
] == list(config_util.config_per_platform(config, "zone"))