2
Doxyfile
2
Doxyfile
@@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 2025.12.2
|
||||
PROJECT_NUMBER = 2025.12.3
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -5,7 +5,7 @@ Constants already defined in esphome.const are not duplicated here and must be i
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import Any
|
||||
|
||||
from esphome import codegen as cg, config_validation as cv
|
||||
from esphome.const import CONF_ITEMS
|
||||
@@ -96,13 +96,9 @@ class LValidator:
|
||||
return None
|
||||
if isinstance(value, Lambda):
|
||||
# Local import to avoid circular import
|
||||
from .lvcode import CodeContext, LambdaContext
|
||||
from .lvcode import get_lambda_context_args
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# CodeContext does not have get_automation_parameters
|
||||
# so we need to assert the type here
|
||||
assert isinstance(CodeContext.code_context, LambdaContext)
|
||||
args = args or CodeContext.code_context.get_automation_parameters()
|
||||
args = args or get_lambda_context_args()
|
||||
return cg.RawExpression(
|
||||
call_lambda(
|
||||
await cg.process_lambda(value, args, return_type=self.rtype)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import re
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import Any
|
||||
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import image
|
||||
@@ -404,14 +404,9 @@ class TextValidator(LValidator):
|
||||
self, value: Any, args: list[tuple[SafeExpType, str]] | None = None
|
||||
) -> Expression:
|
||||
# Local import to avoid circular import at module level
|
||||
from .lvcode import get_lambda_context_args
|
||||
|
||||
from .lvcode import CodeContext, LambdaContext
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# CodeContext does not have get_automation_parameters
|
||||
# so we need to assert the type here
|
||||
assert isinstance(CodeContext.code_context, LambdaContext)
|
||||
args = args or CodeContext.code_context.get_automation_parameters()
|
||||
args = args or get_lambda_context_args()
|
||||
|
||||
if isinstance(value, dict):
|
||||
if format_str := value.get(CONF_FORMAT):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import abc
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from esphome import codegen as cg
|
||||
from esphome.config import Config
|
||||
@@ -200,6 +201,21 @@ class LvContext(LambdaContext):
|
||||
return self.add(*args)
|
||||
|
||||
|
||||
def get_lambda_context_args() -> list[tuple[SafeExpType, str]]:
|
||||
"""Get automation parameters from the current lambda context if available.
|
||||
|
||||
When called from outside LVGL's context (e.g., from interval),
|
||||
CodeContext.code_context will be None, so return empty args.
|
||||
"""
|
||||
if CodeContext.code_context is None:
|
||||
return []
|
||||
if TYPE_CHECKING:
|
||||
# CodeContext base class doesn't define get_automation_parameters(),
|
||||
# but LambdaContext and LvContext (the concrete implementations) do.
|
||||
assert isinstance(CodeContext.code_context, LambdaContext)
|
||||
return CodeContext.code_context.get_automation_parameters()
|
||||
|
||||
|
||||
class LocalVariable(MockObj):
|
||||
"""
|
||||
Create a local variable and enclose the code using it within a block.
|
||||
|
||||
@@ -4,7 +4,7 @@ from enum import Enum
|
||||
|
||||
from esphome.enum import StrEnum
|
||||
|
||||
__version__ = "2025.12.2"
|
||||
__version__ = "2025.12.3"
|
||||
|
||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||
|
||||
@@ -99,14 +99,11 @@ def storage_should_clean(old: StorageJSON | None, new: StorageJSON) -> bool:
|
||||
|
||||
|
||||
def storage_should_update_cmake_cache(old: StorageJSON, new: StorageJSON) -> bool:
|
||||
if (
|
||||
# ESP32 uses CMake for both Arduino and ESP-IDF frameworks
|
||||
return (
|
||||
old.loaded_integrations != new.loaded_integrations
|
||||
or old.loaded_platforms != new.loaded_platforms
|
||||
) and new.core_platform == PLATFORM_ESP32:
|
||||
from esphome.components.esp32 import FRAMEWORK_ESP_IDF
|
||||
|
||||
return new.framework == FRAMEWORK_ESP_IDF
|
||||
return False
|
||||
) and new.core_platform == PLATFORM_ESP32
|
||||
|
||||
|
||||
def update_storage_json() -> None:
|
||||
|
||||
@@ -9,6 +9,13 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.const import (
|
||||
PLATFORM_BK72XX,
|
||||
PLATFORM_ESP32,
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_RP2040,
|
||||
PLATFORM_RTL87XX,
|
||||
)
|
||||
from esphome.core import EsphomeError
|
||||
from esphome.storage_json import StorageJSON
|
||||
from esphome.writer import (
|
||||
@@ -21,6 +28,7 @@ from esphome.writer import (
|
||||
clean_build,
|
||||
clean_cmake_cache,
|
||||
storage_should_clean,
|
||||
storage_should_update_cmake_cache,
|
||||
update_storage_json,
|
||||
write_cpp,
|
||||
write_gitignore,
|
||||
@@ -164,6 +172,86 @@ def test_storage_edge_case_from_empty_integrations(
|
||||
assert storage_should_clean(old, new) is False
|
||||
|
||||
|
||||
# Tests for storage_should_update_cmake_cache
|
||||
|
||||
|
||||
@pytest.mark.parametrize("framework", ["arduino", "esp-idf"])
|
||||
def test_storage_should_update_cmake_cache_when_integration_added_esp32(
|
||||
create_storage: Callable[..., StorageJSON],
|
||||
framework: str,
|
||||
) -> None:
|
||||
"""Test cmake cache update triggered when integration added on ESP32."""
|
||||
old = create_storage(
|
||||
loaded_integrations=["api", "wifi"],
|
||||
core_platform=PLATFORM_ESP32,
|
||||
framework=framework,
|
||||
)
|
||||
new = create_storage(
|
||||
loaded_integrations=["api", "wifi", "restart"],
|
||||
core_platform=PLATFORM_ESP32,
|
||||
framework=framework,
|
||||
)
|
||||
assert storage_should_update_cmake_cache(old, new) is True
|
||||
|
||||
|
||||
def test_storage_should_update_cmake_cache_when_platform_changed_esp32(
|
||||
create_storage: Callable[..., StorageJSON],
|
||||
) -> None:
|
||||
"""Test cmake cache update triggered when platforms change on ESP32."""
|
||||
old = create_storage(
|
||||
loaded_integrations=["api", "wifi"],
|
||||
loaded_platforms={"sensor"},
|
||||
core_platform=PLATFORM_ESP32,
|
||||
framework="arduino",
|
||||
)
|
||||
new = create_storage(
|
||||
loaded_integrations=["api", "wifi"],
|
||||
loaded_platforms={"sensor", "binary_sensor"},
|
||||
core_platform=PLATFORM_ESP32,
|
||||
framework="arduino",
|
||||
)
|
||||
assert storage_should_update_cmake_cache(old, new) is True
|
||||
|
||||
|
||||
def test_storage_should_not_update_cmake_cache_when_nothing_changes(
|
||||
create_storage: Callable[..., StorageJSON],
|
||||
) -> None:
|
||||
"""Test cmake cache not updated when nothing changes."""
|
||||
old = create_storage(
|
||||
loaded_integrations=["api", "wifi"],
|
||||
core_platform=PLATFORM_ESP32,
|
||||
framework="arduino",
|
||||
)
|
||||
new = create_storage(
|
||||
loaded_integrations=["api", "wifi"],
|
||||
core_platform=PLATFORM_ESP32,
|
||||
framework="arduino",
|
||||
)
|
||||
assert storage_should_update_cmake_cache(old, new) is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"core_platform",
|
||||
[PLATFORM_ESP8266, PLATFORM_RP2040, PLATFORM_BK72XX, PLATFORM_RTL87XX],
|
||||
)
|
||||
def test_storage_should_not_update_cmake_cache_for_non_esp32(
|
||||
create_storage: Callable[..., StorageJSON],
|
||||
core_platform: str,
|
||||
) -> None:
|
||||
"""Test cmake cache not updated for non-ESP32 platforms."""
|
||||
old = create_storage(
|
||||
loaded_integrations=["api", "wifi"],
|
||||
core_platform=core_platform,
|
||||
framework="arduino",
|
||||
)
|
||||
new = create_storage(
|
||||
loaded_integrations=["api", "wifi", "restart"],
|
||||
core_platform=core_platform,
|
||||
framework="arduino",
|
||||
)
|
||||
assert storage_should_update_cmake_cache(old, new) is False
|
||||
|
||||
|
||||
@patch("esphome.writer.clean_build")
|
||||
@patch("esphome.writer.StorageJSON")
|
||||
@patch("esphome.writer.storage_path")
|
||||
|
||||
Reference in New Issue
Block a user