mirror of
https://github.com/esphome/esphome.git
synced 2026-08-24 15:16:20 +00:00
Skip the user_config deep copy unless esphome config --no-defaults needs it
This commit is contained in:
@@ -2601,6 +2601,8 @@ def run_esphome(argv):
|
||||
config = read_config(
|
||||
command_line_substitutions,
|
||||
skip_external_update=skip_external,
|
||||
# Snapshot only needed by `esphome config --no-defaults`.
|
||||
snapshot_user_config=getattr(args, "no_defaults", False),
|
||||
)
|
||||
# Refresh the cache so the next upload/logs hits the fast path
|
||||
# instead of re-running read_config. Skip when the storage
|
||||
|
||||
+33
-11
@@ -1108,6 +1108,7 @@ def validate_config(
|
||||
config: dict[str, Any],
|
||||
command_line_substitutions: dict[str, Any] | None,
|
||||
skip_external_update: bool = False,
|
||||
snapshot_user_config: bool = False,
|
||||
) -> Config:
|
||||
result = Config()
|
||||
|
||||
@@ -1218,11 +1219,13 @@ def validate_config(
|
||||
# Snapshot the user's config before any schema validation defaults are
|
||||
# applied. preload_core_config and later validation steps rewrite entries
|
||||
# in-place with defaulted values; deep-copying here preserves the
|
||||
# user-supplied keys for `esphome config --no-defaults`.
|
||||
result.user_config = copy.deepcopy(config)
|
||||
if substitutions is not None:
|
||||
result.user_config[CONF_SUBSTITUTIONS] = copy.deepcopy(substitutions)
|
||||
result.user_config.move_to_end(CONF_SUBSTITUTIONS, last=False)
|
||||
# user-supplied keys for `esphome config --no-defaults`. The deep copy is
|
||||
# expensive, so it is only taken when that command actually asked for it.
|
||||
if snapshot_user_config:
|
||||
result.user_config = copy.deepcopy(config)
|
||||
if substitutions is not None:
|
||||
result.user_config[CONF_SUBSTITUTIONS] = copy.deepcopy(substitutions)
|
||||
result.user_config.move_to_end(CONF_SUBSTITUTIONS, last=False)
|
||||
|
||||
# 2. Load partial core config
|
||||
import esphome.core.config as core_config
|
||||
@@ -1335,7 +1338,9 @@ class InvalidYAMLError(EsphomeError):
|
||||
|
||||
|
||||
def _load_config(
|
||||
command_line_substitutions: dict[str, Any], skip_external_update: bool = False
|
||||
command_line_substitutions: dict[str, Any],
|
||||
skip_external_update: bool = False,
|
||||
snapshot_user_config: bool = False,
|
||||
) -> Config:
|
||||
"""Load the configuration file."""
|
||||
try:
|
||||
@@ -1344,7 +1349,12 @@ def _load_config(
|
||||
raise InvalidYAMLError(e) from e
|
||||
|
||||
try:
|
||||
return validate_config(config, command_line_substitutions, skip_external_update)
|
||||
return validate_config(
|
||||
config,
|
||||
command_line_substitutions,
|
||||
skip_external_update=skip_external_update,
|
||||
snapshot_user_config=snapshot_user_config,
|
||||
)
|
||||
except EsphomeError:
|
||||
raise
|
||||
except Exception:
|
||||
@@ -1353,10 +1363,16 @@ def _load_config(
|
||||
|
||||
|
||||
def load_config(
|
||||
command_line_substitutions: dict[str, Any], skip_external_update: bool = False
|
||||
command_line_substitutions: dict[str, Any],
|
||||
skip_external_update: bool = False,
|
||||
snapshot_user_config: bool = False,
|
||||
) -> Config:
|
||||
try:
|
||||
return _load_config(command_line_substitutions, skip_external_update)
|
||||
return _load_config(
|
||||
command_line_substitutions,
|
||||
skip_external_update=skip_external_update,
|
||||
snapshot_user_config=snapshot_user_config,
|
||||
)
|
||||
except vol.Invalid as err:
|
||||
raise EsphomeError(f"Error while parsing config: {err}") from err
|
||||
|
||||
@@ -1497,11 +1513,17 @@ def strip_default_ids(config):
|
||||
|
||||
|
||||
def read_config(
|
||||
command_line_substitutions: dict[str, Any], skip_external_update: bool = False
|
||||
command_line_substitutions: dict[str, Any],
|
||||
skip_external_update: bool = False,
|
||||
snapshot_user_config: bool = False,
|
||||
) -> Config | None:
|
||||
_LOGGER.info("Reading configuration %s...", CORE.config_path)
|
||||
try:
|
||||
res = load_config(command_line_substitutions, skip_external_update)
|
||||
res = load_config(
|
||||
command_line_substitutions,
|
||||
skip_external_update=skip_external_update,
|
||||
snapshot_user_config=snapshot_user_config,
|
||||
)
|
||||
except EsphomeError as err:
|
||||
_LOGGER.error("Error while reading config: %s", err)
|
||||
return None
|
||||
|
||||
@@ -370,7 +370,7 @@ def test_validate_config_captures_user_config_snapshot(tmp_path: Path) -> None:
|
||||
"""
|
||||
test_config = _get_test_minimal_valid_config(tmp_path)
|
||||
|
||||
result = config_module.validate_config(test_config, None)
|
||||
result = config_module.validate_config(test_config, None, snapshot_user_config=True)
|
||||
|
||||
# Snapshot is populated.
|
||||
assert result.user_config is not None
|
||||
@@ -393,7 +393,7 @@ def test_validate_config_user_config_snapshot_is_deep_copy(tmp_path: Path) -> No
|
||||
"""
|
||||
test_config = _get_test_minimal_valid_config(tmp_path)
|
||||
|
||||
result = config_module.validate_config(test_config, None)
|
||||
result = config_module.validate_config(test_config, None, snapshot_user_config=True)
|
||||
|
||||
assert result.user_config is not None
|
||||
# preload_core_config injected build_path onto the validated config.
|
||||
@@ -404,6 +404,20 @@ def test_validate_config_user_config_snapshot_is_deep_copy(tmp_path: Path) -> No
|
||||
assert result["esphome"] is not result.user_config["esphome"]
|
||||
|
||||
|
||||
def test_validate_config_skips_user_config_snapshot_by_default(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""Without ``snapshot_user_config`` the deep copy is skipped entirely;
|
||||
only ``esphome config --no-defaults`` needs the snapshot and the copy is
|
||||
too expensive to take on every load.
|
||||
"""
|
||||
test_config = _get_test_minimal_valid_config(tmp_path)
|
||||
|
||||
result = config_module.validate_config(test_config, None)
|
||||
|
||||
assert result.user_config is None
|
||||
|
||||
|
||||
def test_merge_config_preserves_ordered_dict() -> None:
|
||||
"""Test that merge_config preserves OrderedDict type.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user