Skip to content

Commit e2e14cc

Browse files
committed
undefined state variables now throw a NameError exception, instead of returning None
1 parent 8f11a8b commit e2e14cc

File tree

4 files changed

+13
-11
lines changed

4 files changed

+13
-11
lines changed

custom_components/pyscript/state.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,14 @@ def get(cls, var_name):
124124
"""Get a state variable value or attribute from hass."""
125125
parts = var_name.split(".")
126126
if len(parts) != 2 and len(parts) != 3:
127-
raise NameError(f"invalid name {var_name} (should be 'domain.entity')")
127+
raise NameError(f"invalid name '{var_name}' (should be 'domain.entity')")
128128
value = cls.hass.states.get(f"{parts[0]}.{parts[1]}")
129129
if not value:
130-
return None
130+
raise NameError(f"name '{parts[0]}.{parts[1]}' is not defined")
131131
if len(parts) == 2:
132132
return value.state
133+
if parts[2] not in value.attributes:
134+
raise AttributeError(f"state '{parts[0]}.{parts[1]}' has no attribute '{parts[2]}'")
133135
return value.attributes.get(parts[2])
134136

135137
@classmethod

docs/reference.rst

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,8 @@ Also, service names (which are called as functions) take priority over state var
6969
component has a state variable name that collides with one of its services, you’ll need to use
7070
``state.get(name)`` to access that state variable.
7171

72-
Finally, state variables that don’t exist evaluate to ``None``, rather than throwing an exception.
73-
That makes it easy to test if a state variable has a valid value. In contrast, accessing a state
74-
attribute using ``DOMAIN.name.attr`` will throw an exception if the attribute doesn't exist
75-
(``None`` could be a valid attribute value).
72+
Accessing state variables don't exist will throw a ``NameError`` exception, and accessing an
73+
attribute that doesn't exist will throw a ``AttributeError`` exception.
7674

7775
Calling services
7876
----------------
@@ -473,10 +471,10 @@ variable using its string name. The set function also allows you to optionally s
473471
which you can’t do if you are directly assigning to the variable:
474472

475473
``state.get(name)``
476-
Returns the value of the state variable given its string ``name``, or ``None`` if it doesn’t exist.
477-
If ``name`` is a string of the form ``DOMAIN.entity.attr`` then the attribute ``attr`` of the
478-
state variable ``DOMAIN.entity`` is returned; an exception is thrown if that attribute doesn't
479-
exist.
474+
Returns the value of the state variable given its string ``name``. A ``NameError`` exception
475+
is thrown if the name doesn't exist. If ``name`` is a string of the form ``DOMAIN.entity.attr``
476+
then the attribute ``attr`` of the state variable ``DOMAIN.entity`` is returned; an
477+
``AttributeError`` exception is thrown if that attribute doesn't exist.
480478
``state.get_attr(name)``
481479
Returns a ``dict`` of attribute values for the state variable, or ``None``
482480
if it doesn’t exist

tests/test_unique.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ def func6():
199199
#
200200
# now run func4() a few times; each one should stop the last one
201201
#
202+
hass.states.async_set("pyscript.f4var2", 0)
202203
for _ in range(10):
203204
seq_num += 1
204205
hass.states.async_set("pyscript.f4var1", 0)
@@ -222,6 +223,7 @@ def func6():
222223
# start and the rest will not
223224
#
224225
seq_num += 1
226+
hass.states.async_set("pyscript.f5var2", 0)
225227
hass.states.async_set("pyscript.f5var1", 0)
226228
hass.states.async_set("pyscript.f5var1", 1)
227229
assert literal_eval(await wait_until_done(notify_q)) == [

tests/test_unit_eval.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,7 @@ async def test_eval(hass):
896896
["task.executor(5)", "Exception in test line 1 column 14: function is not callable by task.executor()"],
897897
[
898898
"import cmath; exec('xyz = cmath.sqrt(complex(3, 4))', {})",
899-
"Exception in test line 1 column 54: Exception in exec() line 1 column 28: 'sqrt' is not callable (got None)",
899+
"Exception in test line 1 column 54: Exception in exec() line 1 column 6: name 'cmath.sqrt' is not defined",
900900
],
901901
["func1(1)", "Exception in test line 1 column 0: name 'func1' is not defined"],
902902
[

0 commit comments

Comments
 (0)