mirror of
https://github.com/esphome/esphome.git
synced 2026-10-19 04:32:50 +00:00
[core] Add final_validate.get_declaring_config (#20912)
This commit is contained in:
@@ -3,7 +3,7 @@ import contextvars
|
||||
from typing import Any
|
||||
|
||||
import esphome.config_validation as cv
|
||||
from esphome.types import ID, ConfigFragmentType, ConfigPathType
|
||||
from esphome.types import ID, ConfigFragmentType, ConfigPathType, ConfigType
|
||||
|
||||
|
||||
class FinalValidateConfig(ABC):
|
||||
@@ -39,6 +39,21 @@ full_config: contextvars.ContextVar[FinalValidateConfig] = contextvars.ContextVa
|
||||
)
|
||||
|
||||
|
||||
def get_declaring_config(
|
||||
id_: ID, config: FinalValidateConfig | None = None
|
||||
) -> ConfigType:
|
||||
"""Return the config block that declares id_, such as a hub's own config.
|
||||
|
||||
Uses the full config being validated unless config is given.
|
||||
Raises KeyError if the id was not declared, TypeError if its parent is not a dict.
|
||||
"""
|
||||
fconf = full_config.get() if config is None else config
|
||||
declaring = fconf.get_config_for_path(fconf.get_path_for_id(id_)[:-1])
|
||||
if not isinstance(declaring, dict):
|
||||
raise TypeError(f"ID {id_} is not declared in a config block")
|
||||
return declaring
|
||||
|
||||
|
||||
def id_declaration_match_schema(schema):
|
||||
"""A final-validation schema function that applies a schema to the outer config fragment of an
|
||||
ID declaration.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
"""Tests for esphome.final_validate helpers."""
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome import final_validate as fv
|
||||
from esphome.config import Config
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import ID
|
||||
|
||||
|
||||
def _config() -> tuple[Config, ID, dict]:
|
||||
hub_id = ID("my_hub", is_declaration=True)
|
||||
hub = {CONF_ID: hub_id, "mode": "fast"}
|
||||
config = Config()
|
||||
config["other"] = {"x": 1}
|
||||
config["my_comp"] = [{"y": 2}, hub]
|
||||
config.declare_ids.append((hub_id, ["my_comp", 1, CONF_ID]))
|
||||
return config, hub_id, hub
|
||||
|
||||
|
||||
def test_returns_the_declaring_block_from_the_full_config() -> None:
|
||||
config, hub_id, hub = _config()
|
||||
token = fv.full_config.set(config)
|
||||
try:
|
||||
assert fv.get_declaring_config(hub_id) is hub
|
||||
finally:
|
||||
fv.full_config.reset(token)
|
||||
|
||||
|
||||
def test_uses_the_given_config() -> None:
|
||||
config, hub_id, hub = _config()
|
||||
assert fv.get_declaring_config(ID("my_hub"), config) is hub
|
||||
|
||||
|
||||
def test_unknown_id_raises_key_error() -> None:
|
||||
config, _, _ = _config()
|
||||
with pytest.raises(KeyError):
|
||||
fv.get_declaring_config(ID("missing"), config)
|
||||
|
||||
|
||||
def test_non_dict_parent_raises_type_error() -> None:
|
||||
config, _, _ = _config()
|
||||
list_id = ID("in_list", is_declaration=True)
|
||||
config["listed"] = [list_id]
|
||||
config.declare_ids.append((list_id, ["listed", 0]))
|
||||
with pytest.raises(TypeError):
|
||||
fv.get_declaring_config(ID("in_list"), config)
|
||||
Reference in New Issue
Block a user