Put inline comments in templates

Hello the world of automation enthusiasts,

I’m doing more and more complex automations, especially since the editor is more clear.
But I’d like to put comments in some of my templates, as they are becoming really complex.

Is there a way in the Jinja2 to do comments, like in this template:

{% if (now().isoweekday() in [6, 7])
      or (as_timestamp(now()) + (24*3600)) | timestamp_custom('%Y-%m-%d 00:00:00', True) == state_attr('calendar.conges_scolaires','start_time') 
      or ( (states('calendar.conges_scolaires') == 'on')
           and (as_timestamp(now())) | timestamp_custom('%Y-%m-%d 00:00:00', True) != state_attr('calendar.conges_scolaires','end_time') 
         )
      or (as_timestamp(now()) + (24*3600)) | timestamp_custom('%Y-%m-%d 00:00:00', True) == state_attr('calendar.jours_feries_en_belgique','start_time') 
      or ( (states('calendar.jours_feries_en_belgique') == 'on')
           and (as_timestamp(now())) | timestamp_custom('%Y-%m-%d 00:00:00', True) != state_attr('calendar.jours_feries_en_belgique','end_time') 
         )
%}
  set offset=1
{% endif %}

I know that I can put
{# Some comment in Jinja2 #}

But in the massive condition, I’d like to add comment on each line like

{% if (now().isoweekday() in [5, 6]) {# Sat, Sun #}
      or (as_timestamp(now()) + (24*3600)) | timestamp_custom('%Y-%m-%d 00:00:00', True) == state_attr('calendar.conges_scolaires','start_time') {# Tomorrow is a school holiday #}
      or ( (states('calendar.conges_scolaires') == 'on') {# Today is a school holiday... #}
           and (as_timestamp(now())) | timestamp_custom('%Y-%m-%d 00:00:00', True) != state_attr('calendar.conges_scolaires','end_time') {# ... and there is no school tomorrow #}
         )
      or (as_timestamp(now()) + (24*3600)) | timestamp_custom('%Y-%m-%d 00:00:00', True) == state_attr('calendar.jours_feries_en_belgique','start_time') {# Tomorrow is a public holiday #}
      or ( (states('calendar.jours_feries_en_belgique') == 'on') {# Today is a public holiday... #}
           and (as_timestamp(now())) | timestamp_custom('%Y-%m-%d 00:00:00', True) != state_attr('calendar.jours_feries_en_belgique','end_time') {# ... and it's not over yet tomorrow #}
         )
%}

Which is not working

Is there a way?

You cannot nest templates inside templates.

One option to make it more legible with or without comments is to set variables:

{% set tomorrow_0 = today_at() + timedelta(days=1) %}
{% set today_0 = today_at() %}
{% set is_weekend = (now().isoweekday() in [5, 6]) %} {# Sat, Sun #}
{% set con_scol_demain = (tomorrow_0 == state_attr('calendar.conges_scolaires','start_time')|as_datetime|as_local) %} {# Tomorrow is a school holiday #}
{% set con_scol = ( (states('calendar.conges_scolaires') == 'on') and (today_0 != state_attr('calendar.conges_scolaires','end_time')|as_datetime|as_local) ) %} {# Today is a school holiday... and it's not over tomorrow #}
{% set j_feries_demain = (tomorrow_0 == state_attr('calendar.jours_feries_en_belgique','start_time')|as_datetime|as_local) %} {# Tomorrow is a public holiday... #}
{% set j_feries = ( (states('calendar.jours_feries_en_belgique') == 'on') and (today_0 != state_attr('calendar.jours_feries_en_belgique','end_time')|as_datetime|as_local) ) %} {# Today is a public holiday... and it's not over tomorrow #}

{{ is_weekend or con_scol_demain or con_scol or j_feries_demain or j_feries }}

1 Like

Yes, it is more clear, I did it (in french sorry) and do not need comments in the big if like that.

{% set aujourdhui = (as_timestamp(now())) | timestamp_custom('%Y-%m-%d 00:00:00', True) %}
{% set demain = (as_timestamp(now()) + (24*3600)) | timestamp_custom('%Y-%m-%d 00:00:00', True) %}

{% set is_weekend = now().isoweekday() in [6, 7] %}
{% set is_conges_scolaires = states('calendar.conges_scolaires') == 'on' %}
{% set is_ferie = states('calendar.jours_feries_en_belgique') == 'on' %}

{% set debut_conge_scolaire = state_attr('calendar.conges_scolaires','start_time') %}
{% set debut_ferie = state_attr('calendar.jours_feries_en_belgique','start_time') %}
{% set fin_conge_scolaire = state_attr('calendar.conges_scolaires','end_time') %}
{% set fin_ferie = state_attr('calendar.jours_feries_en_belgique','end_time') %}

{% if ( is_weekend ) 
      or ( demain == debut_conge_scolaire )
      or ( (is_conge_scolaire)
           and (aujourdhui != fin_conge_scolaire) 
         )
      or ( demain == debut_ferie )
      or ( (is_ferie)
           and (aujourdhui != fin_ferie) 
         )
%}
  {% set offset = 1 %}
{% endif %} 

{{ states('sensor.uptime_ipad_2') | float >= (1.5 + offset|default(0)) }}

What is also interesting me in your solution is that you seem to have a better way than I do to determine today and tomorrow (that I compare with the string attribute start_date and end_date of the calendar).

I did (as_timestamp(now())) | timestamp_custom('%Y-%m-%d 00:00:00', True) so I can compare with the attribute of the calendar that is always of the form like this:

start_time: 2022-11-11 00:00:00
end_time: 2022-11-12 00:00:00

Can you explain it to me, please?

There are many ways to manipulate time information … I tend to prefer to use datetime objects and timedeltas instead of doing timestamp math, but the exact implementation depends a lot on the inputs and desired output.

When the arguments are left blank, the today_at() function returns a localized datetime object for today’s date at 00:00:00. The timedelta() function lets us add or subtract time values from a datetime object without having to do the conversions necessary with timestamps.

Depending on the calendar integration you are using the “start_time” attribute could be a string or a datetime object. Based on the template you provided yours is a string. To use the today_at() and timedelta() functions you would need to convert them to datetime objects as follows:

Condition with datetime object conversion
{% set aujourdhui = today_at() %}
{% set demain = today_at() + timedelta(days=1) %}

{% set is_weekend = now().isoweekday() in [6, 7] %}
{% set is_conges_scolaires = states('calendar.conges_scolaires') == 'on' %}
{% set is_ferie = states('calendar.jours_feries_en_belgique') == 'on' %}

{% set debut_conge_scolaire = state_attr('calendar.conges_scolaires','start_time') | as_datetime | as_local %}
{% set debut_ferie = state_attr('calendar.jours_feries_en_belgique','start_time') | as_datetime | as_local %}
{% set fin_conge_scolaire = state_attr('calendar.conges_scolaires','end_time') | as_datetime | as_local %}
{% set fin_ferie = state_attr('calendar.jours_feries_en_belgique','end_time') | as_datetime | as_local %}

{% if ( is_weekend ) 
      or ( demain == debut_conge_scolaire )
      or ( (is_conge_scolaire)
           and (aujourdhui != fin_conge_scolaire) 
         )
      or ( demain == debut_ferie )
      or ( (is_ferie)
           and (aujourdhui != fin_ferie) 
         )
%}
  {% set offset = 1 %}
{% endif %} 

{{ states('sensor.uptime_ipad_2') | float >= (1.5 + offset|default(0)) }}
1 Like