# jiinja2 evaluation of default( "string" + var)

**URL:** <https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393>\
**Category:** Ansible Project\
**Created:** [August 30, 2013, 3:38pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393 "2013-08-30T15:38:36Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [August 30, 2013, 3:38pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/1 "2013-08-30T15:38:36Z")

</div>

This works when item.send is defined and http\_send is not:

{{ item.send | default(http\_send) }}

This however fails when item.send is defined and item.context is not:

{{ item.send | default(‘GET /’ + item.context + ‘/healthcheck.jsp’ + ‘\\r\\n\\r\\n’) }}

Somehere the “string” + var expression gets evaluated regardless whether the default clause is used.

Does anybody know a workaround for this, or is this something patcheable in ansible, and if so any poiinters where to look at?

Thanks,

Serge

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [September 2, 2013, 12:47pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/2 "2013-09-02T12:47:56Z")

</div>

​I should have added that by 'not work' I meant on the second example I get  
an error on the undefined variable in the default clause, whilst the  
default clause isn't being used.​

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [September 2, 2013, 2:38pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/3 "2013-09-02T14:38:28Z")

</div>

I would expect the default to not be lazy-evaluated, so this doesn’t seem unusual to me.

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [September 2, 2013, 2:49pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/4 "2013-09-02T14:49:01Z")

</div>

​I'm sorry, not sure what you mean by lazy evaluated.  
Nevertheless, how do you explain the default doesn't get evaluated when  
it's just one variable,  
and \*does\* get evaluated when it's a "string" + var construct?  
In both cases where the initial variable is defined, so no default is  
needed.​

---

<div class="post-metadata">

**Author:** ![C\_Morgan\_Hamill](https://avatars.discourse-cdn.com/v4/letter/c/ebca7d/32.png) [@C\_Morgan\_Hamill](https://forum.ansible.com/u/C_Morgan_Hamill)\
**Post date:** [September 2, 2013, 3:09pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/5 "2013-09-02T15:09:25Z")

</div>

Excerpts from Serge van Ginderachter's message of 2013-09-02 10:49:01 -0400:

> Nevertheless, how do you explain the default doesn't get evaluated when  
> it's just one variable,  
> and \*does\* get evaluated when it's a "string" + var construct?  
> In both cases where the initial variable is defined, so no default is  
> needed.

Not sure why this is the case (haven't actually thought about it), but  
this is actually a behavior of jinja2, not Ansible.

In Python:

&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> import jinja2  
&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t = jinja2.Template('''{{ foo|default("hello " + bar) }}''')

&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t.render(foo='yes', bar='no')  
&nbsp;&nbsp;&nbsp;&nbsp;'yes'

&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t.render(bar='no')  
&nbsp;&nbsp;&nbsp;&nbsp;'hello no'

&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t.render(foo='yes')  
&nbsp;&nbsp;&nbsp;&nbsp;\*snip traceback\*  
&nbsp;&nbsp;&nbsp;&nbsp;Undefined Error: 'foo' is undefined

On the other hand, and this shoudl fix Serge's problem, the following  
works:

&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t = jinja2.Template('''{{ foo|default("hello " ~ bar) }}''')  
&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t.render(foo='yes')  
&nbsp;&nbsp;&nbsp;&nbsp;'yes'

So using the '~' concatenation operator (which also does type coercion  
and you should really just use for this generally) will allow Serge to  
do what he wants.

I am not sure why the '+' operator behaves this way; we could poke in  
jinja2's source or file something in its bug tracker:

&nbsp;&nbsp;&nbsp;&nbsp;\<[https://github.com/mitsuhiko/jinja2/issues&gt](https://github.com/mitsuhiko/jinja2/issues&gt);

---

<div class="post-metadata">

**Author:** ![C\_Morgan\_Hamill](https://avatars.discourse-cdn.com/v4/letter/c/ebca7d/32.png) [@C\_Morgan\_Hamill](https://forum.ansible.com/u/C_Morgan_Hamill)\
**Post date:** [September 2, 2013, 3:10pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/6 "2013-09-02T15:10:19Z")

</div>

Excerpts from C. Morgan Hamill's message of 2013-09-02 11:09:25 -0400:

> &nbsp;&nbsp;&nbsp;&nbsp;\>\>\> import jinja2  
> &nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t = jinja2.Template('''{{ foo|default("hello " + bar) }}''')
> 
> &nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t.render(foo='yes', bar='no')  
> &nbsp;&nbsp;&nbsp;&nbsp;'yes'
> 
> &nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t.render(bar='no')  
> &nbsp;&nbsp;&nbsp;&nbsp;'hello no'
> 
> &nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t.render(foo='yes')  
> &nbsp;&nbsp;&nbsp;&nbsp;\*snip traceback\*  
> &nbsp;&nbsp;&nbsp;&nbsp;Undefined Error: 'foo' is undefined

Sorry, this should be "'bar' is undefined."

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [September 2, 2013, 7:26pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/7 "2013-09-02T19:26:30Z")

</div>

​Thanks! But, wWhilst this indeed works in plain Python​, unluckily it  
doesn't work in ansible ☹

TASK: [debug msg={{var}}]

---

<div class="post-metadata">

**Author:** ![C\_Morgan\_Hamill](https://avatars.discourse-cdn.com/v4/letter/c/ebca7d/32.png) [@C\_Morgan\_Hamill](https://forum.ansible.com/u/C_Morgan_Hamill)\
**Post date:** [September 2, 2013, 8:21pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/8 "2013-09-02T20:21:44Z")

</div>

Excerpts from Serge van Ginderachter's message of 2013-09-02 15:26:30 -0400:

> Thanks! But, whilst this indeed works in plain Python, unluckily it  
> doesn't work in ansible ☹

Hah, I didn't actually test it in Ansible!

That said, it's because Ansible does something like this when running  
everything through jinja2:

&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> import jinja2  
&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> e = jinja2.Environment(undefined=jinja2.StrictUndefined)  
&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t = e.from\_string('''{{ foo|default("hello " ~ bar) }}''')  
&nbsp;&nbsp;&nbsp;&nbsp;\>\>\> t.render(foo='what up')  
&nbsp;&nbsp;&nbsp;&nbsp;\*snip traceback\*  
&nbsp;&nbsp;&nbsp;&nbsp;UndefinedError: 'bar' is undefined

Not sure why Ansible uses 'StrictUndefined' instead of the default  
'jinja2.Undefined', but I assume it's for good reason. Perhaps someone  
more familiar with the code base could jump in. That said, the jinja2  
docs make it clear that 'StrictUndefined' will bark at you for  
attempting to do anything with undefined variables other than testing  
them to see if they are defined.

So there you go!

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [September 2, 2013, 9:08pm UTC](https://forum.ansible.com/t/jiinja2-evaluation-of-default-string-var/13393/9 "2013-09-02T21:08:29Z")

</div>

Exactly.

StrictUndefined is done because we want it to yell at you when variables are undefined.
