def test_ids_are_diff_when_types_are_diff(self): text_input1 = TextInput() text_input1.label = "Label #1" text_input1.default = "Value #1" text_area2 = TextArea() text_area2.label = "Label #1" text_area2.default = "Value #1" element1 = Element() element1.text_input.CopyFrom(text_input1) element2 = Element() element2.text_area.CopyFrom(text_area2) register_widget("text_input", element1.text_input) register_widget("text_input", element2.text_input) self.assertNotEqual(element1.text_input.id, element2.text_area.id)
def test_ids_are_equal_when_proto_is_equal(self): text_input1 = TextInput() text_input1.label = "Label #1" text_input1.default = "Value #1" text_input2 = TextInput() text_input2.label = "Label #1" text_input2.default = "Value #1" element1 = Element() element1.text_input.CopyFrom(text_input1) element2 = Element() element2.text_input.CopyFrom(text_input2) register_widget("text_input", element1.text_input) with self.assertRaises(DuplicateWidgetID): register_widget("text_input", element2.text_input)
def marshall_component(element: Element) -> Union[Any, Type[NoValue]]: element.component_instance.component_name = self.name if self.url is not None: element.component_instance.url = self.url # Normally, a widget's element_hash (which determines # its identity across multiple runs of an app) is computed # by hashing the entirety of its protobuf. This means that, # if any of the arguments to the widget are changed, Streamlit # considers it a new widget instance and it loses its previous # state. # # However! If a *component* has a `key` argument, then the # component's hash identity is determined by entirely by # `component_name + url + key`. This means that, when `key` # exists, the component will maintain its identity even when its # other arguments change, and the component's iframe won't be # remounted on the frontend. # # So: if `key` is None, we marshall the element's arguments # *before* computing its widget_ui_value (which creates its hash). # If `key` is not None, we marshall the arguments *after*. def marshall_element_args(): element.component_instance.json_args = serialized_json_args element.component_instance.special_args.extend(special_args) if key is None: marshall_element_args() widget_value = register_widget( element_type="component_instance", element_proto=element.component_instance, user_key=key, widget_func_name=self.name, ) if key is not None: marshall_element_args() if widget_value is None: widget_value = default elif isinstance(widget_value, ArrowTableProto): widget_value = arrow_table.arrow_proto_to_dataframe( widget_value) # widget_value will be either None or whatever the component's most # recent setWidgetValue value is. We coerce None -> NoValue, # because that's what DeltaGenerator._enqueue expects. return widget_value if widget_value is not None else NoValue
def test_ids_are_diff_when_values_are_diff(self): text_input1 = TextInput() text_input1.label = "Label #1" text_input1.default = "Value #1" text_input2 = TextInput() text_input2.label = "Label #1" text_input2.default = "Value #2" element1 = Element() element1.text_input.CopyFrom(text_input1) element2 = Element() element2.text_input.CopyFrom(text_input2) register_widget("text_input", element1.text_input, user_key="some_key1") register_widget("text_input", element2.text_input, user_key="some_key1") self.assertNotEqual(element1.text_input.id, element2.text_input.id)