@@ -45,6 +45,21 @@ def __setattr__(self, name, value):
4545 self [name ] = value
4646
4747
48+ class _GuardedWidgetState (_State ):
49+ def __init__ (self , * args , ** kwargs ):
50+ super ().__init__ (* args , ** kwargs )
51+ object .__setattr__ (self , "_instantiated_widget_keys" , set ())
52+
53+ def __setitem__ (self , key , value ):
54+ if key in self ._instantiated_widget_keys :
55+ raise RuntimeError (f"{ key } cannot be modified after widget instantiation" )
56+ super ().__setitem__ (key , value )
57+
58+ def mark_instantiated (self , key : str | None ) -> None :
59+ if key :
60+ self ._instantiated_widget_keys .add (key )
61+
62+
4863class _Context :
4964 def __init__ (self , st ):
5065 self ._st = st
@@ -152,6 +167,26 @@ def error(self, text):
152167 self .errors .append (text )
153168
154169
170+ class _GuardedFakeStreamlit (_FakeStreamlit ):
171+ def __init__ (self , * , widget_values = None , session_state = None , button_values = None ):
172+ super ().__init__ (
173+ widget_values = widget_values ,
174+ session_state = session_state ,
175+ button_values = button_values ,
176+ )
177+ self .session_state = _GuardedWidgetState (self .session_state )
178+
179+ def text_input (self , label , * , key = None , value = "" , ** kwargs ):
180+ result = super ().text_input (label , key = key , value = value , ** kwargs )
181+ self .session_state .mark_instantiated (key )
182+ return result
183+
184+ def text_area (self , label , * , key = None , value = "" , ** kwargs ):
185+ result = super ().text_area (label , key = key , value = value , ** kwargs )
186+ self .session_state .mark_instantiated (key )
187+ return result
188+
189+
155190def test_compute_cluster_mode_uses_expected_bitmask ():
156191 result = orchestrate_cluster .compute_cluster_mode (
157192 {"pool" : True , "cython" : True , "rapids" : True },
@@ -1582,7 +1617,7 @@ def test_render_cluster_settings_ui_rewrites_stale_app_child_workers_data_path(m
15821617 (share / "agi" / "workflows" / "session-a" ).mkdir (parents = True )
15831618 stale_data_path = "cluster-share/agi/workflows/session-a/flight_trajectory/dataset"
15841619 session_data_path = "cluster-share/agi/workflows/session-a"
1585- fake_st = _FakeStreamlit (
1620+ fake_st = _GuardedFakeStreamlit (
15861621 widget_values = {
15871622 widget_keys ["cluster_enabled" ]: True ,
15881623 widget_keys ["cython" ]: False ,
@@ -1633,7 +1668,7 @@ def test_render_cluster_settings_ui_rewrites_stale_app_child_workers_data_path(m
16331668 cluster = fake_st .session_state .app_settings ["cluster" ]
16341669 assert cluster ["workflow_session" ] == "session-a"
16351670 assert cluster ["workers_data_path" ] == session_data_path
1636- assert fake_st .session_state [widget_keys ["workers_data_path" ]] == session_data_path
1671+ assert fake_st .session_state [widget_keys ["workers_data_path" ]] == stale_data_path
16371672
16381673
16391674def test_render_cluster_settings_ui_selects_existing_workflow_session_directory (monkeypatch , tmp_path ):
0 commit comments