Attributes for macro templates? How to return multiple values from a macro?

I want to create a macro that will test on my Ical sensor calendar events if a certain date is a work day, and if so, at what time do I start working.

It’s not a problem having a code working to find 1. the boolean value if a mentioned date is a workday and 2. for the start hour in case it’s a workday.

What I would like to have is to get the hour as a variable attribute, but from my testing it doesn’t seem to work.

What I’m looking for would be similar to what we see in the demo template with the ‘my_test_json’ variable:

{{ is_it_workday('2023-06-01') }}

would return a boolean value and

{{ is_it_workday('2023-06-01').time }}

would have the start time of my work.

Is there any way to realize this, or get a similar practical result in a way not too unelegant?

(Of course I know there are solutions like returning the hour if workday and nothing if else. But I want the actual answer to my question since there are different cases where I would want mulitple values from a macro.)

Return a JSON-format string and process the return with |from_json. You wouldn’t get the state+attributes structure though.

1 Like

Seems like a good idea, in case the state+attribute structure isn’t possible. I never produced a JSON format string yet, but I may find out how.

Simple example for pasting into the Template Editor, returns 25 and 64:

{% macro powers(x) %}
{{ {'squared': x**2, 'cubed': x**3}|to_json }}
{% endmacro %}

{{ (powers(5)|from_json).squared }}
{{ (powers(4)|from_json).cubed }}

Create a dictionary object with the “attributes” you want as key/value pairs, output it via the |to_json filter to turn it into a JSON string.

Then turn the output from every time you call it back into the dictionary object with |from_json.

It’s a little messier than being able to directly return and manipulate an object, but as far as I am aware it’s the closest option you have.

3 Likes

Thanks a lot! I was just about to publish the version I succeeded to realize, when I saw your last response.

Here is how my actual code look like, more or less:

For my macro:

(some code here determining the values if it is a workday and if so at what time)
+

{%- set is_workday_hour = {'isworkday': booleanvar_wday, 'hour': hour_var}|to_json -%}
        
{{ is_workday_hour }}

{%- endmacro %}

Any template using the macro would start like this:

{% from 'tools.jinja' import is_workday %}
{% set wd = is_workday('2023-04-29')|from_json %}

Then I can follow with this:

wd.isworkday (would return true or false)
wd.hour (would return the time or None)

without having to call a second or third time the whole processing of the macro.

So it does need some extra lines, but not so many and this is a good enough solution for me.

Thanks again for pointing me in the right direction.

1 Like