mirror of
https://github.com/esphome/esphome.git
synced 2025-10-04 02:52:22 +01:00
@@ -1,9 +1,10 @@
|
|||||||
|
from ast import literal_eval
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import jinja2 as jinja
|
import jinja2 as jinja
|
||||||
from jinja2.nativetypes import NativeEnvironment
|
from jinja2.sandbox import SandboxedEnvironment
|
||||||
|
|
||||||
TemplateError = jinja.TemplateError
|
TemplateError = jinja.TemplateError
|
||||||
TemplateSyntaxError = jinja.TemplateSyntaxError
|
TemplateSyntaxError = jinja.TemplateSyntaxError
|
||||||
@@ -70,7 +71,7 @@ class Jinja:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, context_vars):
|
def __init__(self, context_vars):
|
||||||
self.env = NativeEnvironment(
|
self.env = SandboxedEnvironment(
|
||||||
trim_blocks=True,
|
trim_blocks=True,
|
||||||
lstrip_blocks=True,
|
lstrip_blocks=True,
|
||||||
block_start_string="<%",
|
block_start_string="<%",
|
||||||
@@ -90,6 +91,15 @@ class Jinja:
|
|||||||
**SAFE_GLOBAL_FUNCTIONS,
|
**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):
|
def expand(self, content_str):
|
||||||
"""
|
"""
|
||||||
Renders a string that may contain Jinja expressions or statements
|
Renders a string that may contain Jinja expressions or statements
|
||||||
@@ -106,7 +116,7 @@ class Jinja:
|
|||||||
override_vars = content_str.upvalues
|
override_vars = content_str.upvalues
|
||||||
try:
|
try:
|
||||||
template = self.env.from_string(content_str)
|
template = self.env.from_string(content_str)
|
||||||
result = template.render(override_vars)
|
result = self.safe_eval(template.render(override_vars))
|
||||||
if isinstance(result, Undefined):
|
if isinstance(result, Undefined):
|
||||||
# This happens when the expression is simply an undefined variable. Jinja does not
|
# This happens when the expression is simply an undefined variable. Jinja does not
|
||||||
# raise an exception, instead we get "Undefined".
|
# raise an exception, instead we get "Undefined".
|
||||||
|
@@ -5,6 +5,9 @@ substitutions:
|
|||||||
var21: '79'
|
var21: '79'
|
||||||
value: 33
|
value: 33
|
||||||
values: 44
|
values: 44
|
||||||
|
position:
|
||||||
|
x: 79
|
||||||
|
y: 82
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
name: test
|
name: test
|
||||||
@@ -26,3 +29,7 @@ test_list:
|
|||||||
- Literal $values ${are not substituted}
|
- Literal $values ${are not substituted}
|
||||||
- ["list $value", "${is not}", "${substituted}"]
|
- ["list $value", "${is not}", "${substituted}"]
|
||||||
- {"$dictionary": "$value", "${is not}": "${substituted}"}
|
- {"$dictionary": "$value", "${is not}": "${substituted}"}
|
||||||
|
- |-
|
||||||
|
{{{ "x", "79"}, { "y", "82"}}}
|
||||||
|
- '{{{"AA"}}}'
|
||||||
|
- '"HELLO"'
|
||||||
|
@@ -8,6 +8,9 @@ substitutions:
|
|||||||
var21: "79"
|
var21: "79"
|
||||||
value: 33
|
value: 33
|
||||||
values: 44
|
values: 44
|
||||||
|
position:
|
||||||
|
x: 79
|
||||||
|
y: 82
|
||||||
|
|
||||||
test_list:
|
test_list:
|
||||||
- "$var1"
|
- "$var1"
|
||||||
@@ -27,3 +30,7 @@ test_list:
|
|||||||
- !literal Literal $values ${are not substituted}
|
- !literal Literal $values ${are not substituted}
|
||||||
- !literal ["list $value", "${is not}", "${substituted}"]
|
- !literal ["list $value", "${is not}", "${substituted}"]
|
||||||
- !literal {"$dictionary": "$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"' }
|
||||||
|
Reference in New Issue
Block a user