j2cli icon indicating copy to clipboard operation
j2cli copied to clipboard

An option to keep undefined variables

Open pietervogelaar opened this issue 5 years ago • 5 comments

It would be nice to support multi stage rendering as described at https://stackoverflow.com/a/53134416/948378.

from jinja2 import Environment, BaseLoader,DebugUndefined
rtemplate =Environment(loader=BaseLoader,undefined=DebugUndefined) \
           .from_string("{{ a }} is defined, but {{ b}} is undefined")

print(rtemplate.render({"a":"a"}))

# The result is:
# a is defined, but {{ b }} is undefined

pietervogelaar avatar Jun 11 '19 11:06 pietervogelaar

Hi @pietervogelaar , thank you for the feature request: you're not the first one asking about this :)

I wonder what the use case could be. Wouldn't it be possible in your case to merge the variables before rendering a template, instead of doing this multi-stage rendering? Isn't it prone to errors?

kolypto avatar Jun 28 '19 11:06 kolypto

DebugUndefined may indeed be an unorthodox way to implement multi-stage processing. But since this a feature already implemented in Jinja2, and exposing it adds practically no cruft to j2cli, I can't see why not to expose it if someone has a use for it.

Personally, I use this behaviour in its original scope: debugging. If you are trying to render and debug 100+ templates you can generate your output using DebugUndefined. Then a grep -r '{{' output/ will help you quickly fix missing variables in the context, without going through multiple runs.

Note that I had implemented this (among other things) in #13. The patch is now outdated, but it should be straightforward to pull the relevant lines. I can send a new PR only with this part if you're too busy.

m000 avatar Jul 28 '19 16:07 m000

My use case for this is that I want to template GitHub Actions workflow files. GitHub Actions uses ${{ }} for it's own templating. I want to ignore those and just template what I pass data for.

e.g. j2cli should just ignore secrets if --undefined is set in my data.

          token: ${{ secrets.MY_TOKEN }}

But it errors:

jinja2.exceptions.UndefinedError: 'secrets' is undefined

This is quite disappointing because it means j2cli (and perhaps jinja2 altogether) is unusable for my use case. I'll need to find another templating engine if I can't figure out a way to keep undefined variables.

peter-evans avatar Dec 06 '23 11:12 peter-evans

My use case for this is that I want to template GitHub Actions workflow files. GitHub Actions uses ${{ }} for it's own templating. I want to ignore those and just template what I pass data for.

e.g. j2cli should just ignore secrets if --undefined is set in my data.

          token: ${{ secrets.MY_TOKEN }}

But it errors:

jinja2.exceptions.UndefinedError: 'secrets' is undefined

This is quite disappointing because it means j2cli (and perhaps jinja2 altogether) is unusable for my use case. I'll need to find another templating engine if I can't figure out a way to keep undefined variables.

How about using {% raw %} blocks https://jinja.palletsprojects.com/en/3.1.x/templates/#escaping?

Or perhaps a custom filter, where you would write {{ "secrets.MY_TOKEN" | ghaction_env }} in the template, to get ${{ secrets.MY_TOKEN }} in the output?

m000 avatar Dec 06 '23 11:12 m000

{% raw %} probably would work, but I found the best workaround was just to change the start/end delimiters with --customize custom.py.

# custom.py file for j2cli

def j2_environment_params():
    return dict(
        # modify the variable delimiters to avoid conflicts with GitHub Actions templating
        variable_start_string='<<',
        variable_end_string='>>',
    )

Sorry for the noise in this issue. I still think it would be a useful feature to just ignore undefined keys, though.

peter-evans avatar Dec 06 '23 12:12 peter-evans