Skip to content

AttributeError: 'StateVal' object has no attribute 'old' #831

Description

@ALERTua

This is not about the 2.0.0; this behavior is old.
Using the .old StateVal field can not be reliable, as it exists only if it is set.

OCCUPANCY = 'binary_sensor.office_motion_cat_mat_presence'

@state_trigger(
    f"{OCCUPANCY} == 'on' and {OCCUPANCY}.old == 'off'",
    watch=[
        OCCUPANCY,
    ],
    state_hold=10,
    state_hold_false=15,
)
def cat_mat_on(trigger_type=None, var_name=None, value=None, old_value=None, context=None, **kwargs):
    ...

results in

2026-05-03 11:12:05.212 ERROR (MainThread) [custom_components.pyscript.file.cat_mat] 
  File "/config/custom_components/pyscript/decorators/base.py", line 56, in check_expression_vars
    return await self._ast_expression.eval(state_vars)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/pyscript/cat_mat.py", line 1, in file.cat_mat.cat_mat_on_func @state_trigger()
    binary_sensor.office_motion_cat_mat_presence == 'on' and binary_sensor.office_motion_cat_mat_presence.old == 'off'
                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'StateVal' object has no attribute 'old'

While I know I can use the old_value kwarg, I have several @state_trigger decorators around this function. To use old_value, I am forced to have a dedicated dummy function that contains the old_value check and returns the main function. This balloons the code and the newcomer experience.
E.g.:

def cat_mat_on(trigger_type=None, var_name=None, value=None, old_value=None, context=None, **kwargs):
    ...

@state_trigger(
    f"{MOTION} in ('large')",
    watch=[
        MOTION,
    ],
    state_hold=5,
    state_hold_false=15,
)
def cat_mat_on_1(trigger_type=None, var_name=None, value=None, old_value=None, context=None, **kwargs):
    cat_mat_on(trigger_type=trigger_type, var_name=var_name, value=value, old_value=old_value, context=context, **kwargs)

@state_trigger(
    f"{OCCUPANCY} == 'on'",
    watch=[
        OCCUPANCY,
    ],
    state_hold=10,
    state_hold_false=15,
)
def cat_mat_on_2(trigger_type=None, var_name=None, value=None, old_value=None, context=None, **kwargs):
    if old_value != 'off':
        return
    
    cat_mat_on(trigger_type=trigger_type, var_name=var_name, value=value, old_value=old_value, context=context, **kwargs)

Having this field's default value would solve this for me.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions