Skip to content

NativeEnv evals constants twice #1186

@Qhesz

Description

@Qhesz

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]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions