Pyscript - yet another Python scripting component

Tags: #<Tag:0x00007f739670dbc0> #<Tag:0x00007f739670daa8>

I’ve developed an initial version of pyscript, a new component for user-created python scripting.

The git repository is home-assistant-pyscript, which contains three directories (one for the component itself, a testing directory, and the markdown documentation, as rendered by github).

This integration allows you to write Python functions and scripts that can implement a wide range of automation, logic and triggers. State variables are bound to Python variables, and services are callable as Python functions, so it’s easy and concise to implement logic.

Functions you write can be configured to be called as a service or run upon time, state-change or event triggers. Functions can also call any service, fire events and set state variables. Functions can sleep or wait for additional changes in state variables or events, without slowing or affecting other operations. You can think of these functions as small programs that run in parallel, independently of each other, and they could be active for extended periods of time.

State, event and time triggers are specified by Python function decorators (the “@” lines immediately before each function definition). A state trigger can be any Python expression using state variables - the trigger is evaluated only when a state variable it references changes, and the trigger occurs when the expression is true or non-zero. A time trigger could be a single event (eg: date and time), a repetitive event (eg: at a particular time each day or weekday, or daily relative to sunrise or sunset, or any regular time period within an optional range), or using cron syntax (where events occur periodically based on a concise specification of ranges of minutes, hours, days of week, days of month and months). An event trigger specifies the event type, and an optional Python trigger test based on the event data that runs the Python function if true.

Pyscript implements a Python interpreter using the ast parser output, in a fully async manner. That allows several of the “magic” features to be implemented in a seamless Pythonesque manner, such as binding of variables to states, and functions to services. Pyscript supports imports, although the valid import list is restricted for security reasons. Pyscript does not (yet) support some language features like declaring new objects, try/except, eval, and some syntax like “with”. Pyscript provides a handful of additional built-in functions that connect to Hass features, like logging, accessing state variables as strings (if you need to compute their names dynamically), sleeping, and waiting for triggers.

Pyscript provides functionality that complements the existing automations, templates, and triggers. It presents a simplified and more integrated binding for Python scripting than the Python Scripts component, which provides direct access to Hass internals.

Anyhow, I’m very new to Hass (first post), and only a few months into writing Python code, so feedback would be appreciated. It’s possible pyscript uses the internals in incorrect ways, or there are better ways to do things, or some features are missing. Also, the tests are pretty incomplete - for starters I’ve only run them on Python 3.7, but I’ll work to improve coverage soon.

4 Likes

Pyscript has been released as a custom component in HACS. You can install it using HACS -> Integration, select “+” and search for “pyscript”.

I didn’t catch this when it was released, but this is an interesting looking project! I will say that, if you are fairly new to Home Assistant, and you haven’t heard of AppDaemon, you may want to check it out. There is definitely some overlap here in terms of goals and functionality. That being said, even as someone who’s already pretty invested in using AppDaemon, I may have to check this out. I like the use of decorators and the ease of exposing things as services that can be called from Home Assistant, as that’s one thing that AppDaemon does not offer.

Thanks for the pointer about AppDaemon! I wasn’t aware of it. Yes, it has very similar goals and has some similar features - definitely an impressive project. It’s fun to see an independent development result in some similar design choices and features.

In the spectrum of different automations, we have yaml at one end (simplest but least flexible, and can become very verbose), followed by templates (more flexible, but a bit arcane), and Python Scripts at the other (like bare metal - you need a good understanding of internals, and running async tasks and high-level actions takes a lot of scaffolding). Pyscripts and AppDaemon are somewhere in the middle - trying to be flexible and powerful with much of the complexity hidden from the user. I’ll add a mention of AppDaemon to pyscript’s README.md.

For pyscripts I tried to abstract away almost all the usual scaffolding to make it as simple as possible, while trying to maintain a high level of power and expressiveness. AppDaemon does that too - while it does have some scaffolding (but much less than Python Scripts), it offers significant power too.

There are some features in AppDaemon like randomized time intervals and log-based triggers that I could implement in pyscript if there is interest. The accelerated time testing mode is really clever - not sure how I can do that since pyscript runs inside HASS. Maybe I should have a standalone interactive test mode where you can advance the time, set state variables and call services to make sure your code does the right thing?