custom-components / pyscript

Pyscript adds rich Python scripting to HASS
Apache License 2.0
894 stars 47 forks source link

Using state_trigger factory from a module #631

Open cjlapao opened 2 months ago

cjlapao commented 2 months ago

I am trying to write a module that contains some boilerplate code for state_triggers that I wan to call from some other files. If I define the factory in a module, the state seems to be set by the looks of the logs but it is never triggered. now if I define the same factory in the file I am calling then this is working as expected.

On my example I created these two files:

test_trigger.py inside the modules folder and test_dev.py in the pyscript folder

content of test_trigger.py

from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    state: Any = None
    state_trigger: Any = None
    service: Any = None
    log: Any = None
    light: Any = None
    input_boolean: Any = None
    task: Any = None

def trigger_factory_test(id):
    log.debug(f"Creating state change trigger for {id} test6")

    @state_trigger(f"{id}.*")
    def on_change(**args):
        log.debug(f"{id} changed: {args}")

    return on_change

and the test_dev.py

from test_trigger import trigger_factory_test
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    state: Any = None
    state_trigger: Any = None
    service: Any = None
    log: Any = None
    light: Any = None
    input_boolean: Any = None
    task: Any = None

def on_change_from_within(id):
    log.debug(f"Creating state change trigger for {id} from test_dev.py")

    @state_trigger(f"{id}.*")
    def on_change(**args):
        log.debug(f"Something changed: {args}")

    return on_change

f1 = on_change_from_within("light.office_wall_leds")
f2 = trigger_factory_test("light.office_wall_leds")

when the light changes state I see the change on f1 but not from f2, even if I commented out the f1

Do I need to use apps for this?

mefranklin6 commented 4 weeks ago

Possible race condition related to my issue #647 ? You can try instantiating f1 and f2 within the below function so they will be made on boot and after everything else is loaded, or for testing try tying them to a button through state trigger. It's the bare calls in the body of the file that may be the issue here.


@time_trigger
def run_on_startup_or_reload():
    """This function runs automatically once on startup or reload"""
    pass
cjlapao commented 4 weeks ago

Adding them here

@time_trigger
def run_on_startup_or_reload():
    log.debug("Running on startup or reload")
    """This function runs automatically once on startup or reload"""
    f1 = on_change_from_within("light.office_wall_leds")
    f2 = trigger_factory_test("light.office_wall_leds")
    pass

then it makes even the one in the test_dev.py that used to work to fail The file is being correctly loaded as I added another one

@state_trigger("light.office_wall_leds")
def on_change_from_state(**args):
    log.debug(f"{id} changed: {args} from_state")

In the test_dev.py and this is working

Even from a button it does not change the outcome

    @state_trigger(development_button)
def switch_state_changed(**args):
    log.debug(f"Button was pressed: {args}")
    context = args["context"]
    value = args["value"]
    if value == "on_press":
        run_on_startup_or_reload()
    if value == "off_press":
        pass
    if value == "up_press":
        pass
    if value == "down_press":
        pass