Spaces:
Runtime error
Runtime error
File size: 6,985 Bytes
67fb03c |
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# trame_timer_full_demo_v2.py
# Trame (Vuetify v2) – robust, reusable ticking timers for any long-running task
import time
import threading
from trame.app import get_server
from trame.ui.vuetify import SinglePageLayout
from trame.widgets import vuetify as v
# -----------------------------------------------------------------------------
# Server / State
# -----------------------------------------------------------------------------
server = get_server() # Vuetify v2 stack
state = server.state
# Upload stage
state.is_uploading = False
state.upload_elapsed = 0.0
state.upload_progress = 0 # 0..100
state.upload_msg = ""
# Predict stage
state.is_predicting = False
state.predict_elapsed = 0.0
state.predict_progress = 0 # 0..100
state.predict_msg = ""
def _flush_safe():
try:
state.flush()
except Exception:
# Prefer logging in real apps; avoid crashing worker thread
pass
# -----------------------------------------------------------------------------
# Generic, reusable timer helpers
# -----------------------------------------------------------------------------
def start_ticker(flag_key: str, elapsed_key: str, interval_s: float = 0.1):
"""
Start a thread that updates <elapsed_key> while <flag_key> is True.
"""
state[elapsed_key] = 0.0
state[flag_key] = True
_flush_safe()
def _tick():
t0 = time.perf_counter()
while state.get(flag_key, False):
state[elapsed_key] = time.perf_counter() - t0
_flush_safe()
time.sleep(interval_s)
threading.Thread(target=_tick, daemon=True).start()
def stop_ticker(flag_key: str):
state[flag_key] = False
_flush_safe()
def run_with_timer(flag_key: str, elapsed_key: str, work_fn, *args, **kwargs):
"""
Fire-and-forget: starts ticker, runs work_fn(*args, **kwargs) in a thread,
and always stops ticker in a finally-block. Returns the worker thread.
"""
start_ticker(flag_key, elapsed_key)
def _runner():
try:
work_fn(*args, **kwargs)
finally:
stop_ticker(flag_key)
t = threading.Thread(target=_runner, daemon=True)
t.start()
return t
# -----------------------------------------------------------------------------
# Example “work” functions (replace with your real code)
# -----------------------------------------------------------------------------
def _simulate_upload_work():
"""
Simulates an upload: increments progress 0..100 and sets a message.
If cancelled (is_uploading False), it exits cleanly.
"""
state.upload_msg = "Uploading geometry..."
state.upload_progress = 0
_flush_safe()
for i in range(101):
if not state.is_uploading:
state.upload_msg = "Upload cancelled."
_flush_safe()
return
state.upload_progress = i
_flush_safe()
time.sleep(0.05) # Simulate IO chunks
state.upload_msg = "Upload completed."
_flush_safe()
def _simulate_predict_work():
"""
Simulates prediction: increments progress 0..100 and sets a message.
"""
state.predict_msg = "Running prediction..."
state.predict_progress = 0
_flush_safe()
for i in range(101):
if not state.is_predicting:
state.predict_msg = "Prediction cancelled."
_flush_safe()
return
state.predict_progress = i
_flush_safe()
time.sleep(0.06) # Simulate compute steps
state.predict_msg = "Prediction completed."
_flush_safe()
# -----------------------------------------------------------------------------
# Controllers (button hooks)
# -----------------------------------------------------------------------------
def start_upload():
# Reset UI bits for a fresh run
state.upload_progress = 0
state.upload_msg = ""
_flush_safe()
run_with_timer("is_uploading", "upload_elapsed", _simulate_upload_work)
def cancel_upload():
# Just drop the flag; worker and ticker will stop on next loop
stop_ticker("is_uploading")
def start_predict():
state.predict_progress = 0
state.predict_msg = ""
_flush_safe()
run_with_timer("is_predicting", "predict_elapsed", _simulate_predict_work)
def cancel_predict():
stop_ticker("is_predicting")
# -----------------------------------------------------------------------------
# UI (Vuetify v2)
# -----------------------------------------------------------------------------
with SinglePageLayout(server) as layout:
layout.title.set_text("Trame Live Timer – Upload & Predict")
with layout.toolbar:
v.VBtn("Start Upload", color="primary", click=start_upload)
v.VBtn("Cancel Upload", color="error", click=cancel_upload, classes="ml-2")
v.VDivider(vertical=True, classes="mx-4")
v.VBtn("Start Predict", color="secondary", click=start_predict)
v.VBtn("Cancel Predict", color="error", click=cancel_predict, classes="ml-2")
with layout.content:
# Upload panel
v.VSheet(
class_="pa-4 mx-auto",
style="max-width: 600px; margin-top: 40px;"
)(
v.VSubheader("Upload Stage"),
# Progress bar (determinate) – remove v_model & set indeterminate=True if duration unknown
v.VProgressLinear(
v_model=("upload_progress", 0),
height=14,
color="primary",
rounded=True,
v_show=("is_uploading",),
),
v.VSpacer(style="min-height:10px;"),
# Live elapsed time
v.VLabel(
"Elapsed: {{ upload_elapsed.toFixed(2) }} s",
v_show=("is_uploading",),
style="font-weight:600; font-size:14px; color:#1976d2;",
),
v.VSpacer(style="min-height:6px;"),
v.VLabel(("{{ upload_msg }}",), style="opacity:0.8;"),
)
# Predict panel
v.VSheet(
class_="pa-4 mx-auto",
style="max-width: 600px; margin-top: 20px;"
)(
v.VSubheader("Prediction Stage"),
v.VProgressLinear(
v_model=("predict_progress", 0),
height=14,
color="secondary",
rounded=True,
v_show=("is_predicting",),
),
v.VSpacer(style="min-height:10px;"),
v.VLabel(
"Elapsed: {{ predict_elapsed.toFixed(2) }} s",
v_show=("is_predicting",),
style="font-weight:600; font-size:14px;",
),
v.VSpacer(style="min-height:6px;"),
v.VLabel(("{{ predict_msg }}",), style="opacity:0.8;"),
)
# -----------------------------------------------------------------------------
# Run
# -----------------------------------------------------------------------------
if __name__ == "__main__":
server.start()
|