Rendering in native mode performs literal_eval twice on constant values, which leads to unexpected behaviour.
Expected Behavior
>>> NativeEnvironment().from_string(r'''0.000{{ a }}''').render({"a":7})
0.0007
>>> NativeEnvironment().from_string(r'''0.000{{ 7 }}''').render({"a":7})
0.0007
Templates should behave the same way with constants as they do with dynamic variables.
Nothing should be eval'd before the entire template is finished.
Actual Behavior
>>> NativeEnvironment().from_string(r'''0.000{{ a }}''').render({"a":7})
0.07
>>> NativeEnvironment().from_string(r'''0.000{{ 7 }}''').render({"a":7})
0.0007
>>> NativeEnvironment().from_string(r'''{{b}}{{ a }}''').render({"a":7,"b":"0.000"})
0.0007
In the first case the constant 0.000 gets eval'd at template compile time, and truncated to 0.0 before the entire template has been rendered with dynamic data. The template gets eval'd a second time at render time, meaning the constant value has been double eval'd.
In the second case the whole template is constant, and gets eval'd in one go at compile time producing different results.
In the third case the whole template is dynamic, and gets eval'd in one go at render time.
Your Environment
- Python version: 3.7.6
- Jinja version: 2.11.1
Suggested solution
_output_const_repr() should not perform any evals, only render() should perform one eval at the very end. This seems to me like the only sane way to prevent weird double-eval issues like this one.
The preserve_quotes workaround in native_concat would no longer be needed with this change. It appears to have been a previous attempt at fixing this class of problems.
Fixing it this way would also fix the same problem in the underlying root_render_func api:
>>> t = NativeEnvironment().from_string(r'''{{ a }}''')
>>> list(t.root_render_func(t.new_context({"a":"7"})))
['7']
>>> t = NativeEnvironment().from_string(r'''{{"7"}}''')
>>> list(t.root_render_func(t.new_context({"a":"7"})))
[7]
Rendering in native mode performs
literal_evaltwice on constant values, which leads to unexpected behaviour.Expected Behavior
Templates should behave the same way with constants as they do with dynamic variables.
Nothing should be eval'd before the entire template is finished.
Actual Behavior
In the first case the constant
0.000gets eval'd at template compile time, and truncated to0.0before the entire template has been rendered with dynamic data. The template gets eval'd a second time at render time, meaning the constant value has been double eval'd.In the second case the whole template is constant, and gets eval'd in one go at compile time producing different results.
In the third case the whole template is dynamic, and gets eval'd in one go at render time.
Your Environment
Suggested solution
_output_const_repr()should not perform any evals, onlyrender()should perform one eval at the very end. This seems to me like the only sane way to prevent weird double-eval issues like this one.The
preserve_quotesworkaround innative_concatwould no longer be needed with this change. It appears to have been a previous attempt at fixing this class of problems.Fixing it this way would also fix the same problem in the underlying
root_render_funcapi: