ban button after execute
Browse files
gradio-web/gradio_callbacks.py
CHANGED
|
@@ -423,23 +423,40 @@ def on_video_end_transition(uid, ui_phase=None):
|
|
| 423 |
return on_demo_video_end_transition(uid, ui_phase)
|
| 424 |
|
| 425 |
|
| 426 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 427 |
"""Transition from execute video phase back to the action phase."""
|
|
|
|
| 428 |
LOGGER.debug(
|
| 429 |
-
"on_execute_video_end_transition uid=%s
|
| 430 |
_uid_for_log(uid),
|
| 431 |
-
|
| 432 |
)
|
| 433 |
return (
|
| 434 |
gr.update(visible=False), # execution_video_group
|
| 435 |
gr.update(visible=True), # action_phase_group
|
| 436 |
gr.update(visible=True), # control_panel_group
|
| 437 |
gr.update(interactive=True), # options_radio
|
| 438 |
-
gr.update(interactive=
|
| 439 |
gr.update(interactive=True), # restart_episode_btn
|
| 440 |
gr.update(interactive=True), # next_task_btn
|
| 441 |
_live_obs_update(interactive=False), # img_display
|
| 442 |
-
gr.update(interactive=
|
| 443 |
gr.update(interactive=True), # task_hint_display
|
| 444 |
"action_point", # ui_phase_state
|
| 445 |
)
|
|
@@ -1045,7 +1062,7 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1045 |
coords_update=None,
|
| 1046 |
reference_update=gr.update(interactive=True),
|
| 1047 |
task_hint_update=gr.update(interactive=True),
|
| 1048 |
-
|
| 1049 |
show_execution_video=False,
|
| 1050 |
ui_phase="action_point",
|
| 1051 |
):
|
|
@@ -1053,6 +1070,14 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1053 |
execute_video_update = gr.update(value=None, visible=False, playback_position=0)
|
| 1054 |
if coords_update is None:
|
| 1055 |
coords_update = _ui_text("coords", "not_needed")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1056 |
return (
|
| 1057 |
img_update,
|
| 1058 |
log_update,
|
|
@@ -1069,7 +1094,7 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1069 |
coords_update,
|
| 1070 |
reference_update,
|
| 1071 |
task_hint_update,
|
| 1072 |
-
|
| 1073 |
ui_phase,
|
| 1074 |
)
|
| 1075 |
|
|
@@ -1085,7 +1110,10 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1085 |
options_update=gr.update(interactive=False),
|
| 1086 |
reference_update=gr.update(interactive=False),
|
| 1087 |
task_hint_update=gr.update(interactive=False),
|
| 1088 |
-
|
|
|
|
|
|
|
|
|
|
| 1089 |
show_execution_video=False,
|
| 1090 |
)
|
| 1091 |
|
|
@@ -1128,7 +1156,10 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1128 |
options_update=gr.update(choices=_build_radio_choices(session), value=None, interactive=True),
|
| 1129 |
reference_update=gr.update(interactive=True),
|
| 1130 |
task_hint_update=gr.update(interactive=True),
|
| 1131 |
-
|
|
|
|
|
|
|
|
|
|
| 1132 |
show_execution_video=False,
|
| 1133 |
)
|
| 1134 |
|
|
@@ -1153,7 +1184,10 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1153 |
coords_update=coords_str,
|
| 1154 |
reference_update=gr.update(interactive=True),
|
| 1155 |
task_hint_update=gr.update(interactive=True),
|
| 1156 |
-
|
|
|
|
|
|
|
|
|
|
| 1157 |
show_execution_video=False,
|
| 1158 |
)
|
| 1159 |
|
|
@@ -1288,13 +1322,16 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1288 |
execute_video_update = _build_execution_video_update(uid, session)
|
| 1289 |
show_execution_video = execute_video_update.get("visible") is True
|
| 1290 |
radio_choices = _build_radio_choices(session)
|
| 1291 |
-
|
|
|
|
|
|
|
|
|
|
| 1292 |
restart_episode_update = gr.update(interactive=False) if show_execution_video else gr.update(interactive=True)
|
| 1293 |
next_task_update = gr.update(interactive=False) if show_execution_video else gr.update(interactive=True)
|
| 1294 |
exec_btn_update = (
|
| 1295 |
gr.update(interactive=False)
|
| 1296 |
if show_execution_video
|
| 1297 |
-
else gr.update(interactive=
|
| 1298 |
)
|
| 1299 |
options_update = gr.update(
|
| 1300 |
choices=radio_choices,
|
|
@@ -1308,12 +1345,12 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1308 |
# 格式化日志消息为 HTML 格式(支持颜色显示)
|
| 1309 |
formatted_status = format_log_markdown(status)
|
| 1310 |
LOGGER.debug(
|
| 1311 |
-
"execute_step done uid=%s env=%s ep=%s done=%s
|
| 1312 |
_uid_for_log(uid),
|
| 1313 |
getattr(session, "env_id", None),
|
| 1314 |
getattr(session, "episode_idx", None),
|
| 1315 |
done,
|
| 1316 |
-
|
| 1317 |
show_execution_video,
|
| 1318 |
)
|
| 1319 |
|
|
@@ -1330,7 +1367,7 @@ def execute_step(uid, option_idx, coords_str):
|
|
| 1330 |
coords_update=coords_update,
|
| 1331 |
reference_update=reference_update,
|
| 1332 |
task_hint_update=task_hint_update,
|
| 1333 |
-
|
| 1334 |
show_execution_video=show_execution_video,
|
| 1335 |
ui_phase="execution_video" if show_execution_video else "action_point",
|
| 1336 |
)
|
|
|
|
| 423 |
return on_demo_video_end_transition(uid, ui_phase)
|
| 424 |
|
| 425 |
|
| 426 |
+
def _normalize_post_execute_controls_state(state):
|
| 427 |
+
"""Normalize legacy bool and dict payloads for execute-video exit transitions."""
|
| 428 |
+
if isinstance(state, dict):
|
| 429 |
+
exec_interactive = bool(state.get("exec_btn_interactive", True))
|
| 430 |
+
reference_interactive = bool(state.get("reference_action_interactive", True))
|
| 431 |
+
return {
|
| 432 |
+
"exec_btn_interactive": exec_interactive,
|
| 433 |
+
"reference_action_interactive": reference_interactive,
|
| 434 |
+
}
|
| 435 |
+
legacy_exec_interactive = bool(state)
|
| 436 |
+
return {
|
| 437 |
+
"exec_btn_interactive": legacy_exec_interactive,
|
| 438 |
+
"reference_action_interactive": legacy_exec_interactive,
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
|
| 442 |
+
def on_execute_video_end_transition(uid, post_execute_controls_state=True):
|
| 443 |
"""Transition from execute video phase back to the action phase."""
|
| 444 |
+
controls_state = _normalize_post_execute_controls_state(post_execute_controls_state)
|
| 445 |
LOGGER.debug(
|
| 446 |
+
"on_execute_video_end_transition uid=%s controls_state=%s",
|
| 447 |
_uid_for_log(uid),
|
| 448 |
+
controls_state,
|
| 449 |
)
|
| 450 |
return (
|
| 451 |
gr.update(visible=False), # execution_video_group
|
| 452 |
gr.update(visible=True), # action_phase_group
|
| 453 |
gr.update(visible=True), # control_panel_group
|
| 454 |
gr.update(interactive=True), # options_radio
|
| 455 |
+
gr.update(interactive=controls_state["exec_btn_interactive"]), # exec_btn
|
| 456 |
gr.update(interactive=True), # restart_episode_btn
|
| 457 |
gr.update(interactive=True), # next_task_btn
|
| 458 |
_live_obs_update(interactive=False), # img_display
|
| 459 |
+
gr.update(interactive=controls_state["reference_action_interactive"]), # reference_action_btn
|
| 460 |
gr.update(interactive=True), # task_hint_display
|
| 461 |
"action_point", # ui_phase_state
|
| 462 |
)
|
|
|
|
| 1062 |
coords_update=None,
|
| 1063 |
reference_update=gr.update(interactive=True),
|
| 1064 |
task_hint_update=gr.update(interactive=True),
|
| 1065 |
+
post_execute_controls_state=None,
|
| 1066 |
show_execution_video=False,
|
| 1067 |
ui_phase="action_point",
|
| 1068 |
):
|
|
|
|
| 1070 |
execute_video_update = gr.update(value=None, visible=False, playback_position=0)
|
| 1071 |
if coords_update is None:
|
| 1072 |
coords_update = _ui_text("coords", "not_needed")
|
| 1073 |
+
if post_execute_controls_state is None:
|
| 1074 |
+
post_execute_controls_state = {
|
| 1075 |
+
"exec_btn_interactive": True,
|
| 1076 |
+
"reference_action_interactive": True,
|
| 1077 |
+
}
|
| 1078 |
+
normalized_post_execute_controls_state = _normalize_post_execute_controls_state(
|
| 1079 |
+
post_execute_controls_state
|
| 1080 |
+
)
|
| 1081 |
return (
|
| 1082 |
img_update,
|
| 1083 |
log_update,
|
|
|
|
| 1094 |
coords_update,
|
| 1095 |
reference_update,
|
| 1096 |
task_hint_update,
|
| 1097 |
+
normalized_post_execute_controls_state,
|
| 1098 |
ui_phase,
|
| 1099 |
)
|
| 1100 |
|
|
|
|
| 1110 |
options_update=gr.update(interactive=False),
|
| 1111 |
reference_update=gr.update(interactive=False),
|
| 1112 |
task_hint_update=gr.update(interactive=False),
|
| 1113 |
+
post_execute_controls_state={
|
| 1114 |
+
"exec_btn_interactive": False,
|
| 1115 |
+
"reference_action_interactive": False,
|
| 1116 |
+
},
|
| 1117 |
show_execution_video=False,
|
| 1118 |
)
|
| 1119 |
|
|
|
|
| 1156 |
options_update=gr.update(choices=_build_radio_choices(session), value=None, interactive=True),
|
| 1157 |
reference_update=gr.update(interactive=True),
|
| 1158 |
task_hint_update=gr.update(interactive=True),
|
| 1159 |
+
post_execute_controls_state={
|
| 1160 |
+
"exec_btn_interactive": True,
|
| 1161 |
+
"reference_action_interactive": True,
|
| 1162 |
+
},
|
| 1163 |
show_execution_video=False,
|
| 1164 |
)
|
| 1165 |
|
|
|
|
| 1184 |
coords_update=coords_str,
|
| 1185 |
reference_update=gr.update(interactive=True),
|
| 1186 |
task_hint_update=gr.update(interactive=True),
|
| 1187 |
+
post_execute_controls_state={
|
| 1188 |
+
"exec_btn_interactive": True,
|
| 1189 |
+
"reference_action_interactive": True,
|
| 1190 |
+
},
|
| 1191 |
show_execution_video=False,
|
| 1192 |
)
|
| 1193 |
|
|
|
|
| 1322 |
execute_video_update = _build_execution_video_update(uid, session)
|
| 1323 |
show_execution_video = execute_video_update.get("visible") is True
|
| 1324 |
radio_choices = _build_radio_choices(session)
|
| 1325 |
+
post_execute_controls_state = {
|
| 1326 |
+
"exec_btn_interactive": not done,
|
| 1327 |
+
"reference_action_interactive": not done,
|
| 1328 |
+
}
|
| 1329 |
restart_episode_update = gr.update(interactive=False) if show_execution_video else gr.update(interactive=True)
|
| 1330 |
next_task_update = gr.update(interactive=False) if show_execution_video else gr.update(interactive=True)
|
| 1331 |
exec_btn_update = (
|
| 1332 |
gr.update(interactive=False)
|
| 1333 |
if show_execution_video
|
| 1334 |
+
else gr.update(interactive=post_execute_controls_state["exec_btn_interactive"])
|
| 1335 |
)
|
| 1336 |
options_update = gr.update(
|
| 1337 |
choices=radio_choices,
|
|
|
|
| 1345 |
# 格式化日志消息为 HTML 格式(支持颜色显示)
|
| 1346 |
formatted_status = format_log_markdown(status)
|
| 1347 |
LOGGER.debug(
|
| 1348 |
+
"execute_step done uid=%s env=%s ep=%s done=%s post_execute_controls=%s show_execution_video=%s",
|
| 1349 |
_uid_for_log(uid),
|
| 1350 |
getattr(session, "env_id", None),
|
| 1351 |
getattr(session, "episode_idx", None),
|
| 1352 |
done,
|
| 1353 |
+
post_execute_controls_state,
|
| 1354 |
show_execution_video,
|
| 1355 |
)
|
| 1356 |
|
|
|
|
| 1367 |
coords_update=coords_update,
|
| 1368 |
reference_update=reference_update,
|
| 1369 |
task_hint_update=task_hint_update,
|
| 1370 |
+
post_execute_controls_state=post_execute_controls_state,
|
| 1371 |
show_execution_video=show_execution_video,
|
| 1372 |
ui_phase="execution_video" if show_execution_video else "action_point",
|
| 1373 |
)
|
gradio-web/test/test_ui_phase_machine_runtime_e2e.py
CHANGED
|
@@ -2556,7 +2556,7 @@ def test_header_task_switch_to_video_task_shows_demo_phase(monkeypatch):
|
|
| 2556 |
demo.close()
|
| 2557 |
|
| 2558 |
|
| 2559 |
-
def
|
| 2560 |
import gradio_callbacks as cb
|
| 2561 |
import config as config_module
|
| 2562 |
|
|
@@ -2590,7 +2590,7 @@ def test_phase_machine_runtime_local_video_path_end_transition():
|
|
| 2590 |
_ = option_idx, click_coords
|
| 2591 |
self.last_execution_frames = [fake_obs.copy() for _ in range(3)]
|
| 2592 |
self.base_frames.extend(self.last_execution_frames)
|
| 2593 |
-
return fake_obs.copy(),
|
| 2594 |
|
| 2595 |
originals = {
|
| 2596 |
"get_session": cb.get_session,
|
|
@@ -2608,7 +2608,12 @@ def test_phase_machine_runtime_local_video_path_end_transition():
|
|
| 2608 |
with gr.Blocks(title="Native phase machine local video test") as demo:
|
| 2609 |
uid_state = gr.State(value="uid-local-video")
|
| 2610 |
phase_state = gr.State(value="action_point")
|
| 2611 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2612 |
suppress_state = gr.State(value=False)
|
| 2613 |
with gr.Column(visible=True, elem_id="main_interface") as main_interface:
|
| 2614 |
with gr.Column(visible=False, elem_id="video_phase_group") as video_phase_group:
|
|
@@ -2676,7 +2681,7 @@ def test_phase_machine_runtime_local_video_path_end_transition():
|
|
| 2676 |
coords_box,
|
| 2677 |
reference_action_btn,
|
| 2678 |
task_hint_display,
|
| 2679 |
-
|
| 2680 |
phase_state,
|
| 2681 |
],
|
| 2682 |
queue=False,
|
|
@@ -2690,7 +2695,7 @@ def test_phase_machine_runtime_local_video_path_end_transition():
|
|
| 2690 |
|
| 2691 |
execute_video_display.end(
|
| 2692 |
fn=cb.on_execute_video_end_transition,
|
| 2693 |
-
inputs=[uid_state,
|
| 2694 |
outputs=[
|
| 2695 |
execution_video_group,
|
| 2696 |
action_phase_group,
|
|
@@ -2708,7 +2713,7 @@ def test_phase_machine_runtime_local_video_path_end_transition():
|
|
| 2708 |
)
|
| 2709 |
execute_video_display.stop(
|
| 2710 |
fn=cb.on_execute_video_end_transition,
|
| 2711 |
-
inputs=[uid_state,
|
| 2712 |
outputs=[
|
| 2713 |
execution_video_group,
|
| 2714 |
action_phase_group,
|
|
@@ -2818,30 +2823,66 @@ def test_phase_machine_runtime_local_video_path_end_transition():
|
|
| 2818 |
}""",
|
| 2819 |
timeout=2000,
|
| 2820 |
)
|
| 2821 |
-
|
| 2822 |
-
|
| 2823 |
-
|
| 2824 |
-
|
| 2825 |
-
|
| 2826 |
-
|
| 2827 |
-
|
| 2828 |
-
|
| 2829 |
-
|
| 2830 |
-
|
| 2831 |
-
|
| 2832 |
-
|
| 2833 |
-
|
| 2834 |
-
|
| 2835 |
-
|
| 2836 |
-
|
| 2837 |
-
|
| 2838 |
-
|
| 2839 |
-
|
| 2840 |
-
|
| 2841 |
-
"
|
| 2842 |
-
|
| 2843 |
-
|
| 2844 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2845 |
|
| 2846 |
browser.close()
|
| 2847 |
finally:
|
|
@@ -2851,3 +2892,27 @@ def test_phase_machine_runtime_local_video_path_end_transition():
|
|
| 2851 |
finally:
|
| 2852 |
for name, value in originals.items():
|
| 2853 |
setattr(cb, name, value)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2556 |
demo.close()
|
| 2557 |
|
| 2558 |
|
| 2559 |
+
def _run_local_execute_video_transition_test(*, status_text, done, expect_terminal_buttons_disabled):
|
| 2560 |
import gradio_callbacks as cb
|
| 2561 |
import config as config_module
|
| 2562 |
|
|
|
|
| 2590 |
_ = option_idx, click_coords
|
| 2591 |
self.last_execution_frames = [fake_obs.copy() for _ in range(3)]
|
| 2592 |
self.base_frames.extend(self.last_execution_frames)
|
| 2593 |
+
return fake_obs.copy(), status_text, done
|
| 2594 |
|
| 2595 |
originals = {
|
| 2596 |
"get_session": cb.get_session,
|
|
|
|
| 2608 |
with gr.Blocks(title="Native phase machine local video test") as demo:
|
| 2609 |
uid_state = gr.State(value="uid-local-video")
|
| 2610 |
phase_state = gr.State(value="action_point")
|
| 2611 |
+
post_execute_controls_state = gr.State(
|
| 2612 |
+
value={
|
| 2613 |
+
"exec_btn_interactive": True,
|
| 2614 |
+
"reference_action_interactive": True,
|
| 2615 |
+
}
|
| 2616 |
+
)
|
| 2617 |
suppress_state = gr.State(value=False)
|
| 2618 |
with gr.Column(visible=True, elem_id="main_interface") as main_interface:
|
| 2619 |
with gr.Column(visible=False, elem_id="video_phase_group") as video_phase_group:
|
|
|
|
| 2681 |
coords_box,
|
| 2682 |
reference_action_btn,
|
| 2683 |
task_hint_display,
|
| 2684 |
+
post_execute_controls_state,
|
| 2685 |
phase_state,
|
| 2686 |
],
|
| 2687 |
queue=False,
|
|
|
|
| 2695 |
|
| 2696 |
execute_video_display.end(
|
| 2697 |
fn=cb.on_execute_video_end_transition,
|
| 2698 |
+
inputs=[uid_state, post_execute_controls_state],
|
| 2699 |
outputs=[
|
| 2700 |
execution_video_group,
|
| 2701 |
action_phase_group,
|
|
|
|
| 2713 |
)
|
| 2714 |
execute_video_display.stop(
|
| 2715 |
fn=cb.on_execute_video_end_transition,
|
| 2716 |
+
inputs=[uid_state, post_execute_controls_state],
|
| 2717 |
outputs=[
|
| 2718 |
execution_video_group,
|
| 2719 |
action_phase_group,
|
|
|
|
| 2823 |
}""",
|
| 2824 |
timeout=2000,
|
| 2825 |
)
|
| 2826 |
+
if expect_terminal_buttons_disabled:
|
| 2827 |
+
button_snapshot = page.evaluate(
|
| 2828 |
+
"""() => {
|
| 2829 |
+
const resolveButton = (id) => {
|
| 2830 |
+
return document.querySelector(`#${id} button`) || document.querySelector(`button#${id}`);
|
| 2831 |
+
};
|
| 2832 |
+
const execBtn = resolveButton('exec_btn');
|
| 2833 |
+
const refBtn = resolveButton('reference_action_btn');
|
| 2834 |
+
return {
|
| 2835 |
+
execDisabled: execBtn ? execBtn.disabled : null,
|
| 2836 |
+
refDisabled: refBtn ? refBtn.disabled : null,
|
| 2837 |
+
};
|
| 2838 |
+
}"""
|
| 2839 |
+
)
|
| 2840 |
+
assert button_snapshot == {
|
| 2841 |
+
"execDisabled": True,
|
| 2842 |
+
"refDisabled": True,
|
| 2843 |
+
}
|
| 2844 |
+
else:
|
| 2845 |
+
button_snapshot = page.evaluate(
|
| 2846 |
+
"""() => {
|
| 2847 |
+
const resolveButton = (id) => {
|
| 2848 |
+
return document.querySelector(`#${id} button`) || document.querySelector(`button#${id}`);
|
| 2849 |
+
};
|
| 2850 |
+
const execBtn = resolveButton('exec_btn');
|
| 2851 |
+
const refBtn = resolveButton('reference_action_btn');
|
| 2852 |
+
return {
|
| 2853 |
+
execDisabled: execBtn ? execBtn.disabled : null,
|
| 2854 |
+
refDisabled: refBtn ? refBtn.disabled : null,
|
| 2855 |
+
};
|
| 2856 |
+
}"""
|
| 2857 |
+
)
|
| 2858 |
+
assert button_snapshot == {
|
| 2859 |
+
"execDisabled": False,
|
| 2860 |
+
"refDisabled": False,
|
| 2861 |
+
}
|
| 2862 |
+
page.locator("#action_radio input[type='radio']").nth(1).check(force=True)
|
| 2863 |
+
page.wait_for_function(
|
| 2864 |
+
"""(state) => {
|
| 2865 |
+
const liveObs = document.getElementById('live_obs');
|
| 2866 |
+
const coordsRoot = document.getElementById('coords_box');
|
| 2867 |
+
const coordsField = coordsRoot?.querySelector('textarea, input');
|
| 2868 |
+
const logRoot = document.getElementById('log_output');
|
| 2869 |
+
const logField = logRoot?.querySelector('textarea, input');
|
| 2870 |
+
const coordsValue = coordsField ? coordsField.value.trim() : '';
|
| 2871 |
+
const logValue = logField ? logField.value.trim() : (logRoot?.textContent || '').trim();
|
| 2872 |
+
return (
|
| 2873 |
+
!!liveObs &&
|
| 2874 |
+
liveObs.classList.contains(state.waitClass) &&
|
| 2875 |
+
coordsValue === state.coordsPrompt &&
|
| 2876 |
+
logValue === state.waitLog
|
| 2877 |
+
);
|
| 2878 |
+
}""",
|
| 2879 |
+
arg={
|
| 2880 |
+
"waitClass": config_module.LIVE_OBS_POINT_WAIT_CLASS,
|
| 2881 |
+
"coordsPrompt": config_module.UI_TEXT["coords"]["select_point"],
|
| 2882 |
+
"waitLog": config_module.UI_TEXT["log"]["point_selection_prompt"],
|
| 2883 |
+
},
|
| 2884 |
+
timeout=5000,
|
| 2885 |
+
)
|
| 2886 |
|
| 2887 |
browser.close()
|
| 2888 |
finally:
|
|
|
|
| 2892 |
finally:
|
| 2893 |
for name, value in originals.items():
|
| 2894 |
setattr(cb, name, value)
|
| 2895 |
+
|
| 2896 |
+
|
| 2897 |
+
def test_phase_machine_runtime_local_video_path_end_transition():
|
| 2898 |
+
_run_local_execute_video_transition_test(
|
| 2899 |
+
status_text="Executing: pick",
|
| 2900 |
+
done=False,
|
| 2901 |
+
expect_terminal_buttons_disabled=False,
|
| 2902 |
+
)
|
| 2903 |
+
|
| 2904 |
+
|
| 2905 |
+
def test_phase_machine_runtime_local_video_path_end_transition_terminal_success():
|
| 2906 |
+
_run_local_execute_video_transition_test(
|
| 2907 |
+
status_text="SUCCESS",
|
| 2908 |
+
done=True,
|
| 2909 |
+
expect_terminal_buttons_disabled=True,
|
| 2910 |
+
)
|
| 2911 |
+
|
| 2912 |
+
|
| 2913 |
+
def test_phase_machine_runtime_local_video_path_end_transition_terminal_failed():
|
| 2914 |
+
_run_local_execute_video_transition_test(
|
| 2915 |
+
status_text="Executing: pick | FAILED",
|
| 2916 |
+
done=True,
|
| 2917 |
+
expect_terminal_buttons_disabled=True,
|
| 2918 |
+
)
|
gradio-web/test/test_ui_text_config.py
CHANGED
|
@@ -83,16 +83,22 @@ def test_on_video_end_transition_uses_configured_action_prompt(monkeypatch, relo
|
|
| 83 |
assert result[5] == "action_point"
|
| 84 |
|
| 85 |
|
| 86 |
-
def
|
| 87 |
callbacks = reload_module("gradio_callbacks")
|
| 88 |
|
| 89 |
-
result = callbacks.on_execute_video_end_transition(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
assert result[0]["visible"] is False
|
| 92 |
assert result[1]["visible"] is True
|
| 93 |
assert result[2]["visible"] is True
|
| 94 |
assert result[3]["interactive"] is True
|
| 95 |
-
assert result[4]["interactive"] is
|
| 96 |
assert result[5]["interactive"] is True
|
| 97 |
assert result[6]["interactive"] is True
|
| 98 |
assert result[8]["interactive"] is True
|
|
@@ -100,6 +106,29 @@ def test_on_execute_video_end_transition_preserves_log_and_restores_controls(rel
|
|
| 100 |
assert result[10] == "action_point"
|
| 101 |
|
| 102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
def test_on_demo_video_play_disables_button_and_sets_single_use_state(monkeypatch, reload_module):
|
| 104 |
reload_module("config")
|
| 105 |
callbacks = reload_module("gradio_callbacks")
|
|
|
|
| 83 |
assert result[5] == "action_point"
|
| 84 |
|
| 85 |
|
| 86 |
+
def test_on_execute_video_end_transition_restores_controls_for_non_terminal_state(reload_module):
|
| 87 |
callbacks = reload_module("gradio_callbacks")
|
| 88 |
|
| 89 |
+
result = callbacks.on_execute_video_end_transition(
|
| 90 |
+
"uid-1",
|
| 91 |
+
{
|
| 92 |
+
"exec_btn_interactive": True,
|
| 93 |
+
"reference_action_interactive": True,
|
| 94 |
+
},
|
| 95 |
+
)
|
| 96 |
|
| 97 |
assert result[0]["visible"] is False
|
| 98 |
assert result[1]["visible"] is True
|
| 99 |
assert result[2]["visible"] is True
|
| 100 |
assert result[3]["interactive"] is True
|
| 101 |
+
assert result[4]["interactive"] is True
|
| 102 |
assert result[5]["interactive"] is True
|
| 103 |
assert result[6]["interactive"] is True
|
| 104 |
assert result[8]["interactive"] is True
|
|
|
|
| 106 |
assert result[10] == "action_point"
|
| 107 |
|
| 108 |
|
| 109 |
+
def test_on_execute_video_end_transition_keeps_terminal_buttons_disabled(reload_module):
|
| 110 |
+
callbacks = reload_module("gradio_callbacks")
|
| 111 |
+
|
| 112 |
+
result = callbacks.on_execute_video_end_transition(
|
| 113 |
+
"uid-1",
|
| 114 |
+
{
|
| 115 |
+
"exec_btn_interactive": False,
|
| 116 |
+
"reference_action_interactive": False,
|
| 117 |
+
},
|
| 118 |
+
)
|
| 119 |
+
|
| 120 |
+
assert result[0]["visible"] is False
|
| 121 |
+
assert result[1]["visible"] is True
|
| 122 |
+
assert result[2]["visible"] is True
|
| 123 |
+
assert result[3]["interactive"] is True
|
| 124 |
+
assert result[4]["interactive"] is False
|
| 125 |
+
assert result[5]["interactive"] is True
|
| 126 |
+
assert result[6]["interactive"] is True
|
| 127 |
+
assert result[8]["interactive"] is False
|
| 128 |
+
assert result[9]["interactive"] is True
|
| 129 |
+
assert result[10] == "action_point"
|
| 130 |
+
|
| 131 |
+
|
| 132 |
def test_on_demo_video_play_disables_button_and_sets_single_use_state(monkeypatch, reload_module):
|
| 133 |
reload_module("config")
|
| 134 |
callbacks = reload_module("gradio_callbacks")
|
gradio-web/ui_layout.py
CHANGED
|
@@ -952,7 +952,12 @@ def create_ui_blocks():
|
|
| 952 |
delete_callback=cleanup_user_session,
|
| 953 |
)
|
| 954 |
ui_phase_state = gr.State(value=PHASE_INIT)
|
| 955 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 956 |
current_task_env_state = gr.State(value=None)
|
| 957 |
suppress_next_option_change_state = gr.State(value=False)
|
| 958 |
|
|
@@ -1393,7 +1398,7 @@ def create_ui_blocks():
|
|
| 1393 |
|
| 1394 |
execute_video_display.end(
|
| 1395 |
fn=on_execute_video_end_transition,
|
| 1396 |
-
inputs=[uid_state,
|
| 1397 |
outputs=[
|
| 1398 |
execution_video_group,
|
| 1399 |
action_phase_group,
|
|
@@ -1418,7 +1423,7 @@ def create_ui_blocks():
|
|
| 1418 |
)
|
| 1419 |
execute_video_display.stop(
|
| 1420 |
fn=on_execute_video_end_transition,
|
| 1421 |
-
inputs=[uid_state,
|
| 1422 |
outputs=[
|
| 1423 |
execution_video_group,
|
| 1424 |
action_phase_group,
|
|
@@ -1542,7 +1547,7 @@ def create_ui_blocks():
|
|
| 1542 |
coords_box,
|
| 1543 |
reference_action_btn,
|
| 1544 |
task_hint_display,
|
| 1545 |
-
|
| 1546 |
ui_phase_state,
|
| 1547 |
],
|
| 1548 |
show_progress="hidden",
|
|
|
|
| 952 |
delete_callback=cleanup_user_session,
|
| 953 |
)
|
| 954 |
ui_phase_state = gr.State(value=PHASE_INIT)
|
| 955 |
+
post_execute_controls_state = gr.State(
|
| 956 |
+
value={
|
| 957 |
+
"exec_btn_interactive": True,
|
| 958 |
+
"reference_action_interactive": True,
|
| 959 |
+
}
|
| 960 |
+
)
|
| 961 |
current_task_env_state = gr.State(value=None)
|
| 962 |
suppress_next_option_change_state = gr.State(value=False)
|
| 963 |
|
|
|
|
| 1398 |
|
| 1399 |
execute_video_display.end(
|
| 1400 |
fn=on_execute_video_end_transition,
|
| 1401 |
+
inputs=[uid_state, post_execute_controls_state],
|
| 1402 |
outputs=[
|
| 1403 |
execution_video_group,
|
| 1404 |
action_phase_group,
|
|
|
|
| 1423 |
)
|
| 1424 |
execute_video_display.stop(
|
| 1425 |
fn=on_execute_video_end_transition,
|
| 1426 |
+
inputs=[uid_state, post_execute_controls_state],
|
| 1427 |
outputs=[
|
| 1428 |
execution_video_group,
|
| 1429 |
action_phase_group,
|
|
|
|
| 1547 |
coords_box,
|
| 1548 |
reference_action_btn,
|
| 1549 |
task_hint_display,
|
| 1550 |
+
post_execute_controls_state,
|
| 1551 |
ui_phase_state,
|
| 1552 |
],
|
| 1553 |
show_progress="hidden",
|