Pyinfra: Jinja templates do not throw `UndefinedError` as expected

Created on 19 Dec 2020  路  3Comments  路  Source: Fizzadar/pyinfra

Describe the bug
When referencing an undefined variable in a template, Jinja does not throw an UndefinedError as expected in this code:

https://github.com/Fizzadar/pyinfra/blob/c14c6697f4ee8bbddc204ac372f871d854a0d727/pyinfra/operations/files.py#L803-L805

To Reproduce

# /tmp/templates/should_error.j2
{{this_is_not_defined}}
# /tmp/operation.py
from pyinfra.operations import files

files.template(
    name='This should fail',
    src='templates/should_error.j2',
    dest='/tmp/should_error',
)
$ pyinfra some.server.address /tmp/operation.py

Expected behavior
The command above should throw an error such as:

pyinfra.api.exceptions.OperationError: Error in template: /tmp/templates/should_error.j2 (L1): 'this_is_not_defined' is undefined

Meta

  • Include output of pyinfra --support.
System: Darwin
  Platform: Darwin-19.6.0-x86_64-i386-64bit
  Release: 19.6.0
  Machine: x86_64
pyinfra: v1.3
Executable: /Users/mark/.pyenv/versions/pyinfra/bin/pyinfra
Python: 3.7.7 (CPython, Clang 11.0.0 (clang-1100.0.33.17))
  • How was pyinfra installed (source/pip)?

pip

Possible Fix

diff --git a/pyinfra/api/util.py b/pyinfra/api/util.py
index 8980ab92..cfda72d3 100644
--- a/pyinfra/api/util.py
+++ b/pyinfra/api/util.py
@@ -15,7 +15,12 @@ from types import GeneratorType
 import click
 import six

-from jinja2 import Template, TemplateSyntaxError, UndefinedError
+from jinja2 import (
+    TemplateSyntaxError,
+    UndefinedError,
+    Environment,
+    StrictUndefined
+)
 from paramiko import SSHException

 from pyinfra import logger
@@ -202,7 +207,9 @@ def get_template(filename_or_string, is_string=False):
         with open(filename_or_string, 'r') as file_io:
             template_string = file_io.read()

-    TEMPLATES[cache_key] = Template(template_string, keep_trailing_newline=True)
+    TEMPLATES[cache_key] = Environment(
+        undefined=StrictUndefined,
+        keep_trailing_newline=True).from_string(template_string)
     return TEMPLATES[cache_key]
Bug

All 3 comments

I'm very keen on this, wasn't aware jinja2 made it possible to change this behaviour, will implement this fix 馃憤.

Now implemented in https://github.com/Fizzadar/pyinfra/commit/e901b11ede2c8094b3b5f738e1e26a6c05a884b0 (thank you for the patch!), will release in v1.3.1 shortly.

Now released in 1.3.1!

Was this page helpful?
0 / 5 - 0 ratings