Skip to content

Commit 72aff76

Browse files
committed
state.getattr() can now take a StateVar argument
state.get_attr() now logs a deprecated warning. updated docs & tests.
1 parent c0bb8d1 commit 72aff76

File tree

4 files changed

+27
-13
lines changed

4 files changed

+27
-13
lines changed

custom_components/pyscript/state.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ async def setattr(cls, var_attr_name, value):
201201
parts = var_attr_name.split(".")
202202
if len(parts) != 3:
203203
raise NameError(f"invalid name {var_attr_name} (should be 'domain.entity.attr')")
204-
204+
if not cls.exist(f"{parts[0]}.{parts[1]}"):
205+
raise NameError(f"state {parts[0]}.{parts[1]} doesn't exist")
205206
await cls.set(f"{parts[0]}.{parts[1]}", **{parts[2]: value})
206207

207208
@classmethod
@@ -309,13 +310,24 @@ async def service_call(*args, **kwargs):
309310
@classmethod
310311
async def getattr(cls, var_name):
311312
"""Return a dict of attributes for a state variable."""
313+
if isinstance(var_name, StateVal):
314+
attrs = var_name.__dict__.copy()
315+
for discard in STATE_VIRTUAL_ATTRS:
316+
attrs.pop(discard, None)
317+
return attrs
312318
if var_name.count(".") != 1:
313319
raise NameError(f"invalid name {var_name} (should be 'domain.entity')")
314320
value = cls.hass.states.get(var_name)
315321
if not value:
316322
return None
317323
return value.attributes.copy()
318324

325+
@classmethod
326+
async def get_attr(cls, var_name):
327+
"""Return a dict of attributes for a state variable - deprecated."""
328+
_LOGGER.warning("state.get_attr() is deprecated: use state.getattr() instead")
329+
return cls.getattr(var_name)
330+
319331
@classmethod
320332
def completions(cls, root):
321333
"""Return possible completions of state variables."""
@@ -360,7 +372,7 @@ def register_functions(cls):
360372
"state.setattr": cls.setattr,
361373
"state.names": cls.names,
362374
"state.getattr": cls.getattr,
363-
"state.get_attr": cls.getattr, # deprecated form; to be removed
375+
"state.get_attr": cls.get_attr, # deprecated form; to be removed
364376
"state.persist": cls.persist,
365377
"pyscript.config": cls.pyscript_config,
366378
}

docs/new_features.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,15 @@ The new features since 0.32 in master include:
1818

1919
- Pyscript state variables (entity_ids) can be persisted across pyscript reloads and HASS restarts,
2020
from @swazrgb and @dlashua (#48).
21+
- Entities ``domain.entity`` now support a virtual method ``service`` (eg, ``domain.entity.service()``)
22+
that calls the service ``domain.service`` for any service that has an ``entity_id`` parameter, with
23+
that ``entity_id`` set to ``domain.entity``. Proposed by @dlashua (#64).
2124
- ``@state_trigger`` now supports triggering on an attribute change with ``"domain.entity.attr"`` and
2225
any attribute change with ``"domain.entity.*"``, from @dlashua (#82)
2326
- State variables now support virtual attributes ``last_changed`` and ``last_updated`` for the UTC time when state
2427
values or any attribute was last changed.
28+
- State variable attributes can be set by direct assignment, eg: ``DOMAIN.name.attr = value``.
29+
An equivalent new function ``state.setattr()`` allows a specific attribute to be set.
2530
- State variable values (eg, from ``domain.entity`` or ``state.get()``) now include attributes that can be accessed
2631
after they are assigned to another, normal, variable.
2732
- ``@state_trigger`` and ``task.wait_until`` now have an optional ``state_hold`` duration in seconds that requires
@@ -43,15 +48,10 @@ The new features since 0.32 in master include:
4348
directory, and each module's or app's directory. Those files are read and any missing packages are
4449
installed on HASS startup and pyscript reload. If a specific version of a package is needed, it must be
4550
pinned using the format 'package_name==version'. Contributed by @raman325 (#66, #68, #69, #70, #78).
46-
- State variable attributes can be set by direct assignment, eg: ``DOMAIN.name.attr = value``.
47-
An equivalent new function ``state.setattr()`` allows a specific attribute to be set.
4851
- The reload service now takes an optional parameter ``global_ctx`` that specifies just that
4952
global context is reloaded, eg: ``global_ctx="file.my_scripts"``. Proposed by @dlashua (#63).
5053
- The ``state.get_attr()`` function has been renamed ``state.getattr()``. The old function is
51-
still available and will be removed in some future release.
52-
- Entities ``DOMAIN.ENTITY`` now support a virtual method ``SERVICE`` (eg, ``DOMAIN.ENTITY.SERVICE()``)
53-
that calls the service ``DOMAIN.SERVICE`` for any service that has an ``entity_id`` parameter, with
54-
that ``entity_id`` set to ``DOMAIN.ENTITY``. Proposed by @dlashua (#64).
54+
still available and will be removed in some future release (it logs a warning when used).
5555
- VSCode connections to pyscript's Jupyter kernel now work. Two changes were required: VSCode immediately
5656
closes the heartbeat port, which no longer causes pyscript to shut down the kernel. Also, ``stdout``
5757
messages are flushed prior to sending the execute complete message. This is to ensure `log` and `print`

docs/reference.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -693,9 +693,10 @@ which you can’t do if you are directly assigning to the variable:
693693
then the attribute ``attr`` of the state variable ``DOMAIN.entity`` is returned; an
694694
``AttributeError`` exception is thrown if that attribute doesn't exist.
695695
``state.getattr(name)``
696-
Returns a ``dict`` of attribute values for the state variable, or ``None`` if it doesn’t exist.
697-
In pyscript versions 0.32 and earlier, this function was ``state.get_attr()``. That deprecated
698-
name is still supported, but will be removed in a future version.
696+
Returns a ``dict`` of attribute values for the state variable ``name`` string, or ``None`` if it
697+
doesn’t exist. Alternatively, ``name`` can be a state variable. In pyscript versions 0.32 and
698+
earlier, this function was ``state.get_attr()``. That deprecated name is still supported, but
699+
logs a warning message and will be removed in a future version.
699700
``state.names(domain=None)``
700701
Returns a list of all state variable names (ie, ``entity_id``\ s) of a
701702
domain. If ``domain`` is not specified, it returns all HASS state variable (``entity_id``) names.

tests/test_unit_eval.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,12 @@
150150
state.set("pyscript.var1", pyscript.var1, new_attributes={"attr2": 8.5, "attr3": "xyz"})
151151
chk.append(state.getattr("pyscript.var1"))
152152
pyscript.var1.attr2 = "abc"
153-
chk.append(state.getattr("pyscript.var1"))
153+
chk.append(state.getattr(pyscript.var1))
154154
state.set("pyscript.var1", attr1=123)
155155
state.set("pyscript.var1", attr3="def")
156156
chk.append(state.getattr("pyscript.var1"))
157157
pyscript.var1.attr4 = 987
158-
chk.append(state.getattr("pyscript.var1"))
158+
chk.append(state.getattr(pyscript.var1))
159159
state.set("pyscript.var1", new_attributes={"attr2": 9.5, "attr3": "xyz"})
160160
chk.append(state.getattr("pyscript.var1"))
161161
chk.append(pyscript.var1)
@@ -955,6 +955,7 @@ async def test_eval(hass):
955955
],
956956
["assert 1 == 0, 'this is an error'", "Exception in test line 1 column 15: this is an error"],
957957
["assert 1 == 0", "Exception in test line 1 column 12: "],
958+
["pyscript.var1.attr1 = 10", "Exception in test line 1 column 0: state pyscript.var1 doesn't exist"],
958959
[
959960
"import math; math.sinXYZ",
960961
"Exception in test line 1 column 13: module 'math' has no attribute 'sinXYZ'",

0 commit comments

Comments
 (0)