1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-18 07:45:56 +00:00

address bot review

This commit is contained in:
J. Nick Koston
2025-11-15 10:42:44 -06:00
parent 04f445dfaf
commit 3dd570fdd0
3 changed files with 42 additions and 23 deletions

View File

@@ -716,18 +716,17 @@ async def get_variable_with_full_id(id_: ID) -> tuple[ID, "MockObj"]:
return await CORE.get_variable_with_full_id(id_) return await CORE.get_variable_with_full_id(id_)
def _try_deduplicate_lambda(lambda_expr: LambdaExpression) -> str | None: def _get_shared_lambda_name(lambda_expr: LambdaExpression) -> str:
"""Try to deduplicate a lambda expression. """Get the shared function name for a lambda expression.
If an identical lambda was already generated, returns the name of the If an identical lambda was already generated, returns the existing shared
shared function. Otherwise, creates a new shared function and stores it. function name. Otherwise, creates a new shared function and returns its name.
Args: Args:
lambda_expr: The lambda expression to potentially deduplicate lambda_expr: The lambda expression to deduplicate
Returns: Returns:
The name of the shared function if this lambda should be deduplicated, The name of the shared function for this lambda (either existing or newly created)
None if this is the first occurrence (caller should use original lambda)
""" """
# Create a unique key from the lambda content, parameters, and return type # Create a unique key from the lambda content, parameters, and return type
content = lambda_expr.content content = lambda_expr.content
@@ -837,10 +836,9 @@ async def process_lambda(
lambda_expr = LambdaExpression( lambda_expr = LambdaExpression(
parts, parameters, capture, return_type, location parts, parameters, capture, return_type, location
) )
func_name = _try_deduplicate_lambda(lambda_expr) func_name = _get_shared_lambda_name(lambda_expr)
if func_name is not None: # Return a shared function reference instead of inline lambda
# Return a shared function reference instead of inline lambda return SharedFunctionLambdaExpression(func_name, parameters, return_type)
return SharedFunctionLambdaExpression(func_name, parameters, return_type)
return LambdaExpression(parts, parameters, capture, return_type, location) return LambdaExpression(parts, parameters, capture, return_type, location)

View File

@@ -1,4 +1,4 @@
"""Tests for the binary sensor component.""" """Tests for the text component."""
from esphome.core import CORE from esphome.core import CORE
@@ -58,7 +58,7 @@ def test_text_config_value_mode_set(generate_main):
assert "it_3->traits.set_mode(text::TEXT_MODE_PASSWORD);" in main_cpp assert "it_3->traits.set_mode(text::TEXT_MODE_PASSWORD);" in main_cpp
def test_text_config_lamda_is_set(generate_main): def test_text_config_lambda_is_set(generate_main) -> None:
""" """
Test if lambda is set for lambda mode (optimized with stateless lambda and deduplication) Test if lambda is set for lambda mode (optimized with stateless lambda and deduplication)
""" """

View File

@@ -22,8 +22,8 @@ def test_deduplicate_identical_lambdas() -> None:
) )
# Try to deduplicate them # Try to deduplicate them
func_name1 = cg._try_deduplicate_lambda(lambda1) func_name1 = cg._get_shared_lambda_name(lambda1)
func_name2 = cg._try_deduplicate_lambda(lambda2) func_name2 = cg._get_shared_lambda_name(lambda2)
# Both should get the same function name (deduplication happened) # Both should get the same function name (deduplication happened)
assert func_name1 == func_name2 assert func_name1 == func_name2
@@ -46,8 +46,8 @@ def test_different_lambdas_not_deduplicated() -> None:
return_type=cg.RawExpression("int"), return_type=cg.RawExpression("int"),
) )
func_name1 = cg._try_deduplicate_lambda(lambda1) func_name1 = cg._get_shared_lambda_name(lambda1)
func_name2 = cg._try_deduplicate_lambda(lambda2) func_name2 = cg._get_shared_lambda_name(lambda2)
# Different lambdas should get different function names # Different lambdas should get different function names
assert func_name1 != func_name2 assert func_name1 != func_name2
@@ -71,8 +71,8 @@ def test_different_return_types_not_deduplicated() -> None:
return_type=cg.RawExpression("float"), # Different return type return_type=cg.RawExpression("float"), # Different return type
) )
func_name1 = cg._try_deduplicate_lambda(lambda1) func_name1 = cg._get_shared_lambda_name(lambda1)
func_name2 = cg._try_deduplicate_lambda(lambda2) func_name2 = cg._get_shared_lambda_name(lambda2)
# Different return types = different functions # Different return types = different functions
assert func_name1 != func_name2 assert func_name1 != func_name2
@@ -94,8 +94,8 @@ def test_different_parameters_not_deduplicated() -> None:
return_type=cg.RawExpression("int"), return_type=cg.RawExpression("int"),
) )
func_name1 = cg._try_deduplicate_lambda(lambda1) func_name1 = cg._get_shared_lambda_name(lambda1)
func_name2 = cg._try_deduplicate_lambda(lambda2) func_name2 = cg._get_shared_lambda_name(lambda2)
# Different parameters = different functions # Different parameters = different functions
assert func_name1 != func_name2 assert func_name1 != func_name2
@@ -111,7 +111,7 @@ def test_flush_lambda_dedup_declarations() -> None:
return_type=cg.RawExpression("int"), return_type=cg.RawExpression("int"),
) )
cg._try_deduplicate_lambda(lambda1) cg._get_shared_lambda_name(lambda1)
# Check that declaration was stored # Check that declaration was stored
assert cg._KEY_LAMBDA_DEDUP_DECLARATIONS in CORE.data assert cg._KEY_LAMBDA_DEDUP_DECLARATIONS in CORE.data
@@ -154,7 +154,7 @@ def test_lambda_deduplication_counter() -> None:
capture="", capture="",
return_type=cg.RawExpression("int"), return_type=cg.RawExpression("int"),
) )
func_name = cg._try_deduplicate_lambda(lambda_expr) func_name = cg._get_shared_lambda_name(lambda_expr)
assert func_name == f"shared_lambda_{i}" assert func_name == f"shared_lambda_{i}"
@@ -171,3 +171,24 @@ def test_lambda_format_body() -> None:
assert lambda1.format_body() == "return 42;" assert lambda1.format_body() == "return 42;"
# With source would need a proper source object, skip for now # With source would need a proper source object, skip for now
def test_stateful_lambdas_not_deduplicated() -> None:
"""Test that stateful lambdas (non-empty capture) are not deduplicated."""
# _get_shared_lambda_name is only called for stateless lambdas (capture == "")
# Stateful lambdas bypass deduplication entirely in process_lambda
# Verify that a stateful lambda would NOT get deduplicated
# by checking it's not in the stateless dedup cache
stateful_lambda = cg.LambdaExpression(
parts=["return x + y;"],
parameters=[],
capture="=", # Non-empty capture means stateful
return_type=cg.RawExpression("int"),
)
# Stateful lambdas should NOT be passed to _get_shared_lambda_name
# This is enforced by the `if capture == ""` check in process_lambda
# We verify the lambda has a non-empty capture
assert stateful_lambda.capture != ""
assert stateful_lambda.capture == "="