2021.04 breaking changes and catching "RUN ACTIONS"

I have a project that makes extensive use of blueprints, and several of those rely on the user pressing “RUN ACTIONS” as part of the first-time initialization workflow.

Previously, I could catch this in a blueprint with the template {{ trigger is not defined }} in a choose block and go on about my way. With the 2021.04 release this approach no longer works and instead errors out. What I’m trying to do now is to replace that logic but cannot seem to find the magic test that will reliably do so.

Here’s an example blueprint:

blueprint:
  name: "RUN ACTIONS test blueprint"
  domain: automation
trigger: []

action:
  - service: mqtt.publish
    data:
      topic: "debug"
      payload: "test1: {{ trigger | default('foo') }}"
  - service: mqtt.publish
    data:
      topic: "debug"
      payload: "test2: {{ trigger.platform | default('foo') }}"
  - service: mqtt.publish
    data:
      topic: "debug"
      payload: "test3: {% if trigger.platform == 'None' %}foo{% else %}bar{% endif %}"
  - service: mqtt.publish
    data:
      topic: "debug"
      payload: "test4: {% if trigger.platform == '' %}foo{% else %}bar{% endif %}"

The results published to MQTT look like this:

test1: {'platform': None}
test2: None
test3: bar
test4: bar

Further complicating things is that the change also suggests this behavior is going to change again with the 2021.10 release. As a result, I’m hoping to find a solution that will work today, and also hopefully not break in 6 months when the behavior changes once again.

2 Likes

I have found that the following test works under 2021.04, but it fails to execute under earlier versions: {{ trigger.platform|lower == 'none' }}.

However, it appears that I can combine the two in an or statement:

{{ (trigger is not defined) or (trigger.platform|lower == 'none') }}

This is pretty ugly and feels like it’s going to break again in October. It’d be really helpful if we can get some disposition on how this should be implemented in a manner that works with older releases and also isn’t scheduled to blow up come October.

{% set v = trigger | default({}) %}
{{ trigger != {} }}

there’s plenty of other options like this that will work, and the code will not break in october unless ‘platform’ is removed from the dict. So check against an empty dict.

{{ trigger is not defined or ('platform' in trigger and trigger.platform) }}

or

{{ trigger is not defined or trigger.platform is none }}

or…

You get the point.

probably the easiest is

{{ trigger | default(none) is not none }}

EDIT: Sorry, none is the correct test, not None.

2 Likes

The Jinja Ninja kills it again, thanks for the save @petro!

1 Like

So, I was solving a slightly different problem than this (trying to deal with the exception-handling for what I want to be optionally set selectors) but think what I ended up on should still work here.

Difference in my case was that I had the selectors defaulting to none/null and then defined into script/automation variables (because it seemed cleaner to do it the once and avoid default filtering everywhere else) , so once you’re in-script there’s (understandably) no templated exception-handling based on is defined anymore. Not exactly the issue for you since you can use trigger directly, but seems like similar problem to properly catching the possibilities between null/none/(un)defined state that seem to need different formal tests.

What I ended up on was along the lines of:

variables:
  sensor_input: !input sensor_input
conditions: {{ states(sensor_input) if sensor_input }}

Or in your case it should simplify all the way down to:

{{ true if trigger }}

since if trigger seems to properly render whether trigger is undefined or defined as a null.

But definitely interested if anyone sees an issue to the approach that I haven’t run across yet.

EDIT: Immediately looked back at it and decided I was wrong, and that suggestion would do something but not actually match your needs? But thinking maybe it’s:

{{ true if not trigger.platform }}

That wouldn’t work for versions that are not updated to the latest, that would cause errors in those version. He needed something that worked in old and new versions to appease his userbase.

1 Like

Whoops, yeah, can’t drop the | default filter on that one for backward-compatibility.

Hazy but stubborn impression in the back of my mind that if x vs x is not none makes some difference beyond aesthetics, but still fried enough from the process of creating and then (maybe?) solving my own problems that I don’t trust myself to doublecheck the thought now even if I had the energy.