Why does 'None' appear to be handled inconsistently?

In the Template editor, I have the following code and output:

{{state_attr('device_tracker.life360_mom','address')}} 
None

{{is_state_attr('device_tracker.life360_mom','address', None)}}
False

{{ states.device_tracker.life360_mom.attributes.address == None}}
True

Why do the the second and third templates have different outputs?

Thanks.

And to add to the confusion, these return consistent results:

{{state_attr('device_tracker.life360_mom','driving')}}
False

{{is_state_attr('device_tracker.life360_mom','driving', False)}}
True

{{ states.device_tracker.life360_mom.attributes.driving == False}}
True

Look at the very first post pinned at the top of the forum telling you how to ask a good question… Start with a title that actually says what you need help with and go from there…

That’s exactly what I needed. Someone to explain the given outputs. If it had to be more specific then the title would have contained the entire post.

Going back to the topic, can you explain?

It’s treating ‘None’ as a string here, I think.

What does dev-states show as the values for all the attributes of this entity?

By this logic, all titles should simply say: “I have a question.” :man_shrugging:

David made a valid point. Your post’s title is vague. It stands to reason that the majority of the posts here are looking for an explanation.

The title should capture the essence of your question: Why does None appear to be handled inconsistently?

3 Likes

None is how a null value is represented. For example, I have an entity whose attribute, pattern, is reported to be null in the States page:

Screenshot%20from%202019-07-24%2009-10-50

When tested in the Template Editor, it behaves exactly the same way as your device_tracker's attribute does:

I don’t have insight into how the is_state_attr function performs its comparisons but it’s clear it doesn’t like comparing to a null value. In contrast, the equivalence operator == handles a null value properly.

Your second example, involving true and false, works as one would expect. A boolean value (true/false) is never a null value so is_state_attr handles it correctly.


EDIT
The function is_state_attr is located in Home Assistant’s template.py file. I believe this line of code is responsible for how it handles a comparison with None (null value).

return attr is not None and attr == value

It returns a result but only if its not None (except in this case, it is None so it returns nothing).

2 Likes

Thanks for the explanation. It makes more sense now.

It’s just strange (to me at least) that is_state_attr and == behave the way they do.

If None is considered null (which essentially means unknown), then it should not be possible to compare an unknown value with an == operator.

On the other hand, is_something may have been a better way to test whether a value is null or not, similar to is defined.

The title should capture the essence of your question: Why does None appear to be handled inconsistently?

I may have worded it that way had I realized that (None handled inconsistently unlike True) before submitting the question. As you would notice, I only observed that after results of further investigation (my second post).

Edit: Nevertheless, I will try to use better titles next time.

Null value is no value which isn’t quite the same as unknown value. It may sound like quibbling about semantics but there is a difference. If I haven’t been able to acquire a value then it’s reported to be unknown (a string). If I acquired it and it’s null then it’s reported to be None (a constant).

FWIW, when Home Assistant reports unknown that’s a string value. Here’s an example of an entity with an unknown state. When compared to the string 'unknown' it evaluates to True. It’s False when compared to unknown (there’s no constant called unknown) or to None (because it’s not null; its value is … unknown).

Screenshot%20from%202019-07-24%2011-04-56

1 Like

The answer is in the code. Basically, is_state_attr checks attr is not None, which guarantees that it will always return False if the value is None. Your check using == bypasses that extra condition.

I don’t see this mentioned in the documentation, so it probably needs to be updated to mention that behavior.

2 Likes

I think the is_state_attr function is dealing with a ‘corner-case situation’. Here’s what I mean:

is_state_attr calls the state_attr function with this line:

attr = state_attr(hass, entity_id, name)

The state_attr function gets the entity with this:

state_obj = _get_state(hass, entity_id)

Then, if state_obj is not None, it proceeds to get the attribute’s value and returns it to is_state_attr.

    if state_obj is not None:
        return state_obj.attributes.get(name) # if attribute value is None, it returns None

However, and here’s the interesting part, is state_obj is None then it immediately returns None to is_state_attr (which, in turn, reports False). Effectively, None is used like a flag to indicate the entity_id it received doesn’t exist.

The ‘corner-case situation’ is if the entity does exist but has a value that’s None. The following two lines get executed and the attribute’s true value, None, is returned to is_state_attr.

    if state_obj is not None:
        return state_obj.attributes.get(name) 

In other words, the attribute’s legitimate value, None, is misinterpreted to be the flag that’s used when indicating the entity_id is non-existent.

1 Like

Not to say that I agree or disagree with the code, but I interpret the logic more like a shortcut - if entity_id does not exist, then attributes (and values) also do not exist.

Agreed. However, in this ‘corner case’:

  • state_attr determines the entity_id does exist
  • the entity_id’s attribute exists
  • the attribute’s value is null (None)
  • the value (None) is passed back to is_state_attr
  • is_state_attr reports False because it treats all received None values to mean one thing: the entity_id doesn’t exist

Yes, I understand and fully agree.

I was simply avoiding to say that the implementation (in my opinion) is flawed :slight_smile:

The resolution for is_state_attr() is handled by this line of code:

return attr is not None and attr == value

attr contains the value inside the attribute. So when attr is None, that section of the if statement resolves to false. Even if attr == value, the first section of the return statement resolves false, so no matter what, you’ll get false if the attribute is null/None.

1 Like