1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-03 18:42:23 +01:00

[substitutions] fix #10825 set evaluation error (#10830)

This commit is contained in:
Javier Peletier
2025-10-01 03:33:56 +02:00
committed by GitHub
parent ab1f8326ee
commit fd3c05b42e
3 changed files with 27 additions and 3 deletions

View File

@@ -1,9 +1,10 @@
from ast import literal_eval
import logging
import math
import re
import jinja2 as jinja
from jinja2.nativetypes import NativeEnvironment
from jinja2.sandbox import SandboxedEnvironment
TemplateError = jinja.TemplateError
TemplateSyntaxError = jinja.TemplateSyntaxError
@@ -70,7 +71,7 @@ class Jinja:
"""
def __init__(self, context_vars):
self.env = NativeEnvironment(
self.env = SandboxedEnvironment(
trim_blocks=True,
lstrip_blocks=True,
block_start_string="<%",
@@ -90,6 +91,15 @@ class Jinja:
**SAFE_GLOBAL_FUNCTIONS,
}
def safe_eval(self, expr):
try:
result = literal_eval(expr)
if not isinstance(result, str):
return result
except (ValueError, SyntaxError, MemoryError, TypeError):
pass
return expr
def expand(self, content_str):
"""
Renders a string that may contain Jinja expressions or statements
@@ -106,7 +116,7 @@ class Jinja:
override_vars = content_str.upvalues
try:
template = self.env.from_string(content_str)
result = template.render(override_vars)
result = self.safe_eval(template.render(override_vars))
if isinstance(result, Undefined):
# This happens when the expression is simply an undefined variable. Jinja does not
# raise an exception, instead we get "Undefined".

View File

@@ -5,6 +5,9 @@ substitutions:
var21: '79'
value: 33
values: 44
position:
x: 79
y: 82
esphome:
name: test
@@ -26,3 +29,7 @@ test_list:
- Literal $values ${are not substituted}
- ["list $value", "${is not}", "${substituted}"]
- {"$dictionary": "$value", "${is not}": "${substituted}"}
- |-
{{{ "x", "79"}, { "y", "82"}}}
- '{{{"AA"}}}'
- '"HELLO"'

View File

@@ -8,6 +8,9 @@ substitutions:
var21: "79"
value: 33
values: 44
position:
x: 79
y: 82
test_list:
- "$var1"
@@ -27,3 +30,7 @@ test_list:
- !literal Literal $values ${are not substituted}
- !literal ["list $value", "${is not}", "${substituted}"]
- !literal {"$dictionary": "$value", "${is not}": "${substituted}"}
- |- # Test parsing things that look like a python set of sets when rendered:
{{{ "x", "${ position.x }"}, { "y", "${ position.y }"}}}
- ${ '{{{"AA"}}}' }
- ${ '"HELLO"' }