Skip to content

Simplify setting of attributes #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion custom_components/pyscript/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -1167,9 +1167,15 @@ async def recurse_assign(self, lhs, val):
return
if not isinstance(var_name, str):
raise NotImplementedError(f"unknown lhs type {lhs} (got {var_name}) in assign")
if var_name.find(".") >= 0:
dot_count = var_name.count(".")
if dot_count == 1:
State.set(var_name, val)
return
if dot_count == 2:
State.set_attr(var_name, val)
return
if dot_count > 0:
raise NotImplementedError("variable names may contain at most 2 dots")
if self.curr_func and var_name in self.curr_func.global_names:
self.global_sym_table[var_name] = val
return
Expand Down
24 changes: 22 additions & 2 deletions custom_components/pyscript/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,19 @@ def notify_var_get(cls, var_names, new_vars):
return notify_vars

@classmethod
def set(cls, var_name, value, new_attributes=None, **kwargs):
def set(cls, var_name, value=None, new_attributes=None, **kwargs):
"""Set a state variable and optional attributes in hass."""
if var_name.count(".") != 1:
raise NameError(f"invalid name {var_name} (should be 'domain.entity')")
if new_attributes is None:

state_value = None
if value is None or new_attributes is None:
state_value = cls.hass.states.get(var_name)

if value is None and state_value:
value = state_value.state

if new_attributes is None:
if state_value:
new_attributes = state_value.attributes
else:
Expand All @@ -115,6 +122,18 @@ def set(cls, var_name, value, new_attributes=None, **kwargs):
cls.notify_var_last[var_name] = str(value)
cls.hass.states.async_set(var_name, value, new_attributes)

@classmethod
def set_attr(cls, var_attr_name, value):
"""Set a state variable's attribute in hass."""
parts = var_attr_name.split(".")
if len(parts) != 3:
raise NameError(f"invalid name {var_attr_name} (should be 'domain.entity.attr')")

state_var_name = f"{parts[0]}.{parts[1]}"
attr_name = parts[2]

cls.set(state_var_name, **{attr_name: value})

@classmethod
def exist(cls, var_name):
"""Check if a state variable value or attribute exists in hass."""
Expand Down Expand Up @@ -186,6 +205,7 @@ def register_functions(cls):
functions = {
"state.get": cls.get,
"state.set": cls.set,
"state.set_attr": cls.set_attr,
"state.names": cls.names,
"state.get_attr": cls.get_attr,
"pyscript.config": cls.pyscript_config,
Expand Down
14 changes: 9 additions & 5 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,15 @@ you need their numeric value.

State variables have attributes that can be accessed by adding the name of the attribute, as in
``DOMAIN.name.attr``. The attribute names and their meaning depend on the component that sets them,
so you will need to look at the State tab in the Developer Tools to see the available attributes.
so you will need to look at the State tab in the Developer Tools to see the available attributes. It is also
possible to set these attributes using ``DOMAIN.name.attr = value``.

Starting in version 0.21, when you set a state variable, the existing attributes are not affected
(they were previously removed).

In cases where you need to compute the name of the state variable dynamically, or you need to set or
get the state attributes, you can use the built-in functions ``state.get()``, ``state.get_attr()``
and ``state.set()``; see below.
get the state attributes, you can use the built-in functions ``state.get()``, ``state.get_attr()``,
``state.set_attr()`` and ``state.set()``; see below.

The function ``state.names(domain=None)`` returns a list of all state variable names (ie,
``entity_id``\ s) of a domain. If ``domain`` is not specified, it returns all HASS state
Expand Down Expand Up @@ -536,13 +537,16 @@ which you can’t do if you are directly assigning to the variable:
``state.names(domain=None)``
Returns a list of all state variable names (ie, ``entity_id``\ s) of a
domain. If ``domain`` is not specified, it returns all HASS state variable (``entity_id``) names.
``state.set(name, value, new_attributes=None, **kwargs)``
``state.set(name, value=None, new_attributes=None, **kwargs)``
Sets the state variable to the given value, with the optional attributes. The optional 3rd
argument, ``new_attributes``, should be a ``dict`` and it will overwrite all the existing
attributes if specified. If instead attributes are specified using keyword arguments, then other
attributes will not be affected. If no optional arguments are provided, just the state variable
value is set and the attributes are not changed. To clear the attributes, set
value is set and the attributes are not changed. If no value is provided, just the state arguments
are set. To clear the attributes, set
``new_attributes={}``.
``state.set_attr(name, value)``
Sets the state variable attribute to the given value. The name should look like ``DOMAIN.entity.attr``

Note that in HASS, all state variable values are coerced into strings. For example, if a state
variable has a numeric value, you might want to convert it to a numeric type (eg, using ``int()`` or
Expand Down