Skip to content

Commit 467f271

Browse files
committed
undefined state variables in state trigger/active evaluate to None,
instead of throwing an exception
1 parent cb748a6 commit 467f271

File tree

2 files changed

+34
-22
lines changed

2 files changed

+34
-22
lines changed

docs/reference.rst

+34-20
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Reference
44
Configuration
55
-------------
66

7-
Pyscript has one optional configuration variable that allows any Python package to be imported
7+
Pyscript has one optional configuration setting that allows any Python package to be imported
88
if set, eg:
99

1010
.. code:: yaml
@@ -28,13 +28,12 @@ For example, applications ``my_app1`` and ``my_app2`` would be configured as:
2828
my_app2:
2929
# any settings for my_app2 go here
3030
31-
As explained below, this configuration parameter structure of ``apps`` with entries for each
32-
application by name is used to determine which application scripts are autoloaded. That's the
33-
only configuration structure that pyscript checks - any other parameters can be added and
34-
used as you like.
31+
As explained below, the use of ``apps`` with entries for each application by name below,
32+
is used to determine which application scripts are autoloaded. That's the only configuration
33+
structure that pyscript checks - any other parameters can be added and used as you like.
3534

3635
At startup, pyscript loads the following files. It also unloads and reloads these files when
37-
the ``pyscript.reload`` service is called, and the ``yaml`` configuration is reloaded too:
36+
the ``pyscript.reload`` service is called, which also reloads the ``yaml`` configuration.
3837

3938
``<config>/pyscript/*.py``
4039
all files with a ``.py`` suffix are autoloaded
@@ -110,8 +109,8 @@ Also, service names (which are called as functions) take priority over state var
110109
component has a state variable name that collides with one of its services, you’ll need to use
111110
``state.get(name)`` to access that state variable.
112111

113-
Accessing state variables don't exist will throw a ``NameError`` exception, and accessing an
114-
attribute that doesn't exist will throw a ``AttributeError`` exception.
112+
Accessing state variables that don't exist will throw a ``NameError`` exception, and accessing
113+
an attribute that doesn't exist will throw a ``AttributeError`` exception.
115114

116115
Calling services
117116
----------------
@@ -171,11 +170,11 @@ function.
171170
``@state_trigger`` takes a single string ``str_expr`` that contains any expression based on one or
172171
more state variables, and evaluates to ``True`` or ``False`` (or non-zero or zero). Whenever the
173172
state variables mentioned in the expression change, the expression is evaluated and the trigger
174-
occurs if it evaluates to ``True`` (or non-zero). For each state variable, eg: ``domain.name``, the
175-
prior value if also available to the expression as ``domain.name.old`` in case you want to condition
176-
the trigger on the prior value too.
173+
occurs if it evaluates to ``True`` (or non-zero). For each state variable, eg: ``domain.name``,
174+
the prior value is also available to the expression as ``domain.name.old`` in case you want to
175+
condition the trigger on the prior value too.
177176

178-
Note that all state variables have string values. So you’ll have to do comparisons against string
177+
All state variables in HASS have string values. So you’ll have to do comparisons against string
179178
values or cast the variable to an integer or float. These two examples are essentially equivalent
180179
(note the use of single quotes inside the outer double quotes):
181180

@@ -187,19 +186,19 @@ values or cast the variable to an integer or float. These two examples are essen
187186
188187
@state_trigger("int(domain.light_level) == 255 or int(domain.light2_level) == 0")
189188
190-
although the second will give an exception if the variable string doesn’t represent a valid integer.
189+
although the second will throw an exception if the variable string doesn’t represent a valid integer.
191190
If you want numerical inequalities you should use the second form, since string lexicographic
192191
ordering is not the same as numeric ordering.
193192

194-
You can also use state variable attributes in the trigger expression, with an indenfitier of the
193+
You can also use state variable attributes in the trigger expression, with an idenfitier of the
195194
form ``DOMAIN.name.attr``. Attributes maintain their original type, so there is no need to cast
196195
then to another type.
197196

198197
If you specify ``@state_trigger("True")`` the state trigger will never occur. While that might seem
199198
counter-intuitive, the reason is that the expression will never be evaluated - it takes underlying
200-
state variables in the expression to change before the expression is ever evaluated. Since this
201-
expression has no state variables, it will never be evaluated. You can achieve a state trigger on
202-
any value change with a decorator of the form:
199+
state variables in the expression to change before the expression is evaluated. Since this
200+
expression has no state variables, it will never be evaluated. You can achieve a state trigger
201+
on any value change with a decorator of the form:
203202

204203
.. code:: python
205204
@@ -210,8 +209,8 @@ Because of operator short-circuiting, the expression evaluates to ``True`` witho
210209
value of ``domain.light_level``. So the result is a trigger whenever the state variable changes to
211210
any value. This idea can extend to multiple variables just by stringing them together.
212211

213-
Note that if a state variable is set to the same value, HA doesn’t generate a state change event, so
214-
the ``@state_trigger`` condition will not be checked. It is only evaluated each time a state
212+
Note that if a state variable is set to the same value, HASS doesn’t generate a state change event,
213+
so the ``@state_trigger`` condition will not be checked. It is only evaluated each time a state
215214
variable changes to a new value.
216215

217216
When the trigger occurs and the function is executed (meaning any active checks passed too), keyword
@@ -250,6 +249,13 @@ and all those values will simply get passed in into kwargs as a ``dict``. That
250249
form to use if you have multiple decorators, since each one passes different variables into the
251250
function (although all of them set ``trigger_type``).
252251

252+
Inside ``str_expr``, undefined state variables, undefined state attributes, and undefined
253+
``.old`` variables evaluate to ``None``, rather than throwing an exception. The ``.old`` variable will
254+
be ``None`` the first time the state variable is set (since it has no prior value), and when the
255+
``str_expr`` is being evaluated because a different state variable changed (only the state variable
256+
change that caused ``str_expr`` to be evaluated gets its prior value in ``.old``; any other ``.old``
257+
variables will be ``None`` for that evaluation).
258+
253259
@time_trigger
254260
^^^^^^^^^^^^^
255261

@@ -412,6 +418,14 @@ When any trigger occurs (whether time, state or event), the ``@state_active`` ex
412418
evaluated. If it evaluates to ``False`` (or zero), the trigger is ignored and the trigger function
413419
is not called.
414420

421+
If the trigger was caused by ``@state_trigger``, the prior value of the state variable that
422+
caused the trigger is available to ``str_expr`` with a ``.old`` suffix.
423+
424+
Inside the ``str_expr``, undefined state variables, undefined state attributes, and undefined
425+
``.old`` variables evaluate to `None`, rather than throwing an exception. Any ``.old`` variable
426+
will be ``None`` if the trigger is not a state trigger or if a different state variable change
427+
cause the state trigger.
428+
415429
@time_active
416430
^^^^^^^^^^^^
417431

@@ -910,7 +924,7 @@ Trigger Closures
910924
Pyscript supports trigger functions that are defined as closures, ie: functions defined inside
911925
another function. This allows you to easily create many similar trigger functions that might
912926
differ only in a couple of parameters (eg, a common function in different rooms or for each
913-
media set up). The trigger will be stopped when the function is no longer referenced in
927+
media setup). The trigger will be stopped when the function is no longer referenced in
914928
any scope. Typically the closure function is returned, and the return value is assigned
915929
to a variable. If that variable is re-assigned or deleted, the trigger function will be
916930
destroyed.

docs/tutorial.rst

-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ hey, this is just an example.)
7272
logs:
7373
custom_components.pyscript: info
7474
75-
In a Jupyter session all log messages are displayed, independent of the logger settings.
76-
7775
An example using triggers
7876
-------------------------
7977

0 commit comments

Comments
 (0)