File: hot_reload.py

package info (click to toggle)
python-trame 3.12.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 101,620 kB
  • sloc: python: 13,515; sh: 183; javascript: 93; makefile: 7
file content (92 lines) | stat: -rw-r--r-- 2,667 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from trame.app import get_server
from trame.decorators import hot_reload
from trame.ui.html import DivLayout
from trame.widgets import html

# -----------------------------------------------------------------------------
# Trame setup
# -----------------------------------------------------------------------------

server = get_server()
state, ctrl = server.state, server.controller

# Can be enabled at runtime as well with
# 1. export TRAME_HOT_RELOAD=1
# 2. --hot-reload
server.hot_reload = True


# -----------------------------------------------------------------------------
# Dynamically modify any `ChangeMe` to see the new code execute while
# interacting with the app.
# -----------------------------------------------------------------------------
@ctrl.set("number_reset")
def reset_number():
    print("reset_number::ChangeMe 2")
    state.number = 6
    state.size = 1
    do_someting()


@state.change("number")
def update_number(number, **kwargs):
    print("update_number::ChangeMe", number)
    do_someting()


@hot_reload
def do_someting():
    print("do_someting::ChangeMe")


@ctrl.set("update_ui")
def update_ui():
    with DivLayout(server):
        html.Div("Some content - ChangeMe")
        html.Input(type="range", v_model_number=("number", 6))
        html.Input(type="range", v_model_number=("size", 2))
        html.Button("Reset", click=ctrl.number_reset)
        html.Button("Update", click=ctrl.update_ui)
        html.Div(
            "{{ number }} x {{ i }} = {{ number * i }}",
            v_for="i in size",
            key="i",
        )


# Need to run before start
update_ui()

# -----------------------------------------------------------------------------
# Automatic UI update on file change using watchdog (pip install watchdog)
# -----------------------------------------------------------------------------

try:
    import asyncio
    from pathlib import Path

    from watchdog.events import FileSystemEventHandler
    from watchdog.observers import Observer

    current_event_loop = asyncio.get_event_loop()

    def update_ui():
        with server.state:
            ctrl.update_ui()

    class UpdateUIOnChange(FileSystemEventHandler):
        def on_modified(self, event):
            current_event_loop.call_soon_threadsafe(update_ui)

    observer = Observer()
    observer.schedule(
        UpdateUIOnChange(), str(Path(__file__).parent.absolute()), recursive=False
    )
    observer.start()
except ImportError:
    print("Watchdog not installed so skipping the auto monitoring")

# -----------------------------------------------------------------------------

if __name__ == "__main__":
    server.start()