def test_map_set_del_3837_regression(): """A regression test for `test_map_set_del` that involves too much setup to conveniently use the hypothesis `example` decorator.""" meta1 = stst.mock_metadata( "$$GENERATED_WIDGET_KEY-e3e70682-c209-4cac-629f-6fbed82c07cd-None", 0) meta2 = stst.mock_metadata( "$$GENERATED_WIDGET_KEY-f728b4fa-4248-5e3a-0a5d-2f346baa9455-0", 0) m = SessionState() m["0"] = 0 m.set_unkeyed_widget( meta1, "$$GENERATED_WIDGET_KEY-e3e70682-c209-4cac-629f-6fbed82c07cd-None") m.compact_state() m.set_keyed_widget( meta2, "$$GENERATED_WIDGET_KEY-f728b4fa-4248-5e3a-0a5d-2f346baa9455-0", "0") key = "0" value1 = 0 m[key] = value1 l1 = len(m) del m[key] assert key not in m assert len(m) == l1 - 1
def test_call_callbacks(self): """Test the call_callbacks method in 6 possible cases: 1. A widget does not have a callback 2. A widget's old and new values are equal, so the callback is not called. 3. A widget's callback has no args provided. 4. A widget's callback has just args provided. 5. A widget's callback has just kwargs provided. 6. A widget's callback has both args and kwargs provided. """ prev_states = WidgetStates() _create_widget("trigger", prev_states).trigger_value = True _create_widget("bool", prev_states).bool_value = True _create_widget("bool2", prev_states).bool_value = True _create_widget("float", prev_states).double_value = 0.5 _create_widget("int", prev_states).int_value = 123 _create_widget("string", prev_states).string_value = "howdy!" session_state = SessionState() session_state.set_widgets_from_proto(prev_states) mock_callback = MagicMock() deserializer = lambda x, s: x callback_cases = [ ("trigger", "trigger_value", None, None, None), ("bool", "bool_value", mock_callback, None, None), ("bool2", "bool_value", mock_callback, None, None), ("float", "double_value", mock_callback, (1, ), None), ("int", "int_value", mock_callback, None, { "x": 2 }), ("string", "string_value", mock_callback, (1, ), { "x": 2 }), ] for widget_id, value_type, callback, args, kwargs in callback_cases: session_state.set_metadata( WidgetMetadata( widget_id, deserializer, lambda x: x, value_type=value_type, callback=callback, callback_args=args, callback_kwargs=kwargs, )) states = WidgetStates() _create_widget("trigger", states).trigger_value = True _create_widget("bool", states).bool_value = True _create_widget("bool2", states).bool_value = False _create_widget("float", states).double_value = 1.5 _create_widget("int", states).int_value = 321 _create_widget("string", states).string_value = "!ydwoh" session_state.compact_state() session_state.set_widgets_from_proto(states) session_state.call_callbacks() mock_callback.assert_has_calls( [call(), call(1), call(x=2), call(1, x=2)])
class SessionStateMethodTests(unittest.TestCase): def setUp(self): old_state = {"foo": "bar", "baz": "qux", "corge": "grault"} new_session_state = {"foo": "bar2"} new_widget_state = WStates( { "baz": Value("qux2"), f"{GENERATED_WIDGET_KEY_PREFIX}-foo-None": Value("bar"), }, ) self.session_state = SessionState(old_state, new_session_state, new_widget_state) def test_compact(self): self.session_state.compact_state() assert self.session_state._old_state == { "foo": "bar2", "baz": "qux2", "corge": "grault", f"{GENERATED_WIDGET_KEY_PREFIX}-foo-None": "bar", } assert self.session_state._new_session_state == {} assert self.session_state._new_widget_state == WStates() def test_clear_state(self): self.session_state.clear_state() assert self.session_state._merged_state == {} def test_safe_widget_state(self): new_session_state = MagicMock() wstate = {"foo": "bar"} new_session_state.__getitem__.side_effect = wstate.__getitem__ new_session_state.keys = lambda: {"foo", "baz"} self.session_state = SessionState({}, {}, new_session_state) assert self.session_state._safe_widget_state() == wstate def test_merged_state(self): assert self.session_state._merged_state == { "foo": "bar2", "baz": "qux2", "corge": "grault", f"{GENERATED_WIDGET_KEY_PREFIX}-foo-None": "bar", } def test_filtered_state(self): assert self.session_state.filtered_state == { "foo": "bar2", "baz": "qux2", "corge": "grault", } def test_filtered_state_resilient_to_missing_metadata(self): old_state = {"foo": "bar", "corge": "grault"} new_session_state = {} new_widget_state = WStates( {f"{GENERATED_WIDGET_KEY_PREFIX}-baz": Serialized(None)}, ) self.session_state = SessionState(old_state, new_session_state, new_widget_state) assert self.session_state.filtered_state == { "foo": "bar", "corge": "grault", } def is_new_state_value(self): assert self.session_state.is_new_state_value("foo") assert not self.session_state.is_new_state_value("corge") def test_getitem(self): assert self.session_state["foo"] == "bar2" def test_getitem_error(self): with pytest.raises(KeyError): self.session_state["nonexistent"] def test_setitem(self): assert not self.session_state.is_new_state_value("corge") self.session_state["corge"] = "grault2" assert self.session_state["corge"] == "grault2" assert self.session_state.is_new_state_value("corge") def test_setitem_disallows_setting_created_widget(self): mock_ctx = MagicMock() mock_ctx.widget_ids_this_run = _StringSet() mock_ctx.widget_ids_this_run.add("widget_id") with patch("streamlit.report_thread.get_report_ctx", return_value=mock_ctx): with pytest.raises(StreamlitAPIException) as e: self.session_state._key_id_mapping = {"widget_id": "widget_id"} self.session_state["widget_id"] = "blah" assert "`st.session_state.widget_id` cannot be modified" in str( e.value) def test_setitem_disallows_setting_created_form(self): mock_ctx = MagicMock() mock_ctx.form_ids_this_run = _StringSet() mock_ctx.form_ids_this_run.add("form_id") with patch("streamlit.report_thread.get_report_ctx", return_value=mock_ctx): with pytest.raises(StreamlitAPIException) as e: self.session_state["form_id"] = "blah" assert "`st.session_state.form_id` cannot be modified" in str( e.value) def test_delitem(self): del self.session_state["foo"] assert "foo" not in self.session_state def test_delitem_errors(self): for key in ["_new_session_state", "_new_widget_state", "_old_state"]: with pytest.raises(KeyError): del self.session_state[key] with pytest.raises(KeyError): del self.session_state["nonexistent"] def test_widget_changed(self): assert self.session_state._widget_changed("foo") self.session_state._new_widget_state.set_from_value("foo", "bar") assert not self.session_state._widget_changed("foo") def test_cull_nonexistent(self): generated_widget_key = f"{GENERATED_WIDGET_KEY_PREFIX}-removed_widget" self.session_state._old_state = { "existing_widget": True, generated_widget_key: True, "val_set_via_state": 5, } wstates = WStates() self.session_state._new_widget_state = wstates self.session_state.cull_nonexistent({"existing_widget"}) assert self.session_state["existing_widget"] == True assert generated_widget_key not in self.session_state assert self.session_state["val_set_via_state"] == 5 def test_should_set_frontend_state_value_new_widget(self): # The widget is being registered for the first time, so there's no need # to have the frontend update with a new value. wstates = WStates() self.session_state._new_widget_state = wstates metadata = WidgetMetadata( id=f"{GENERATED_WIDGET_KEY_PREFIX}-0-widget_id_1", deserializer=lambda _, __: 0, serializer=identity, value_type="int_value", ) self.session_state.set_keyed_widget( metadata, f"{GENERATED_WIDGET_KEY_PREFIX}-0-widget_id_1", "widget_id_1") assert (self.session_state.should_set_frontend_state_value( f"{GENERATED_WIDGET_KEY_PREFIX}-0-widget_id_1", "widget_id_1", ) == False) assert self.session_state["widget_id_1"] == 0