def _multiselect( self, label: str, options: OptionSequence, default: Optional[Any] = None, format_func: Callable[[Any], Any] = str, key: Optional[Key] = None, help: Optional[str] = None, on_change: Optional[WidgetCallback] = None, args: Optional[WidgetArgs] = None, kwargs: Optional[WidgetKwargs] = None, *, # keyword-only arguments: disabled: bool = False, ctx: Optional[ScriptRunContext] = None, ) -> List[Any]: key = to_key(key) check_callback_rules(self.dg, on_change) check_session_state_rules(default_value=default, key=key) opt = ensure_indexable(options) # Perform validation checks and return indices base on the default values. def _check_and_convert_to_indices(opt, default_values): if default_values is None and None not in opt: return None if not isinstance(default_values, list): # This if is done before others because calling if not x (done # right below) when x is of type pd.Series() or np.array() throws a # ValueError exception. if is_type(default_values, "numpy.ndarray") or is_type( default_values, "pandas.core.series.Series"): default_values = list(default_values) elif not default_values or default_values in opt: default_values = [default_values] else: default_values = list(default_values) for value in default_values: if value not in opt: raise StreamlitAPIException( "Every Multiselect default value must exist in options" ) return [opt.index(value) for value in default_values] indices = _check_and_convert_to_indices(opt, default) multiselect_proto = MultiSelectProto() multiselect_proto.label = label default_value = [] if indices is None else indices multiselect_proto.default[:] = default_value multiselect_proto.options[:] = [ str(format_func(option)) for option in opt ] multiselect_proto.form_id = current_form_id(self.dg) multiselect_proto.disabled = disabled if help is not None: multiselect_proto.help = dedent(help) def deserialize_multiselect(ui_value: Optional[List[int]], widget_id: str = "") -> List[str]: current_value = ui_value if ui_value is not None else default_value return [opt[i] for i in current_value] def serialize_multiselect(value): return _check_and_convert_to_indices(opt, value) current_value, set_frontend_value = register_widget( "multiselect", multiselect_proto, user_key=key, on_change_handler=on_change, args=args, kwargs=kwargs, deserializer=deserialize_multiselect, serializer=serialize_multiselect, ctx=ctx, ) if set_frontend_value: multiselect_proto.value[:] = _check_and_convert_to_indices( opt, current_value) multiselect_proto.set_value = True self.dg._enqueue("multiselect", multiselect_proto) return cast(List[str], current_value)
def radio( self, label: str, options: OptionSequence, index: int = 0, format_func: Callable[[Any], str] = str, key: Optional[Key] = None, help: Optional[str] = None, on_change: Optional[WidgetCallback] = None, args: Optional[WidgetArgs] = None, kwargs: Optional[WidgetKwargs] = None, ) -> Any: """Display a radio button widget. Parameters ---------- label : str A short label explaining to the user what this radio group is for. options : Sequence, numpy.ndarray, pandas.Series, pandas.DataFrame, or pandas.Index Labels for the radio options. This will be cast to str internally by default. For pandas.DataFrame, the first column is selected. index : int The index of the preselected option on first render. format_func : function Function to modify the display of radio options. It receives the raw option as an argument and should output the label to be shown for that option. This has no impact on the return value of the radio. key : str or int An optional string or integer to use as the unique key for the widget. If this is omitted, a key will be generated for the widget based on its content. Multiple widgets of the same type may not share the same key. help : str An optional tooltip that gets displayed next to the radio. on_change : callable An optional callback invoked when this radio's value changes. args : tuple An optional tuple of args to pass to the callback. kwargs : dict An optional dict of kwargs to pass to the callback. Returns ------- any The selected option. Example ------- >>> genre = st.radio( ... "What\'s your favorite movie genre", ... ('Comedy', 'Drama', 'Documentary')) >>> >>> if genre == 'Comedy': ... st.write('You selected comedy.') ... else: ... st.write("You didn\'t select comedy.") """ key = to_key(key) check_callback_rules(self.dg, on_change) check_session_state_rules(default_value=None if index == 0 else index, key=key) opt = ensure_indexable(options) if not isinstance(index, int): raise StreamlitAPIException("Radio Value has invalid type: %s" % type(index).__name__) if len(opt) > 0 and not 0 <= index < len(opt): raise StreamlitAPIException( "Radio index must be between 0 and length of options") radio_proto = RadioProto() radio_proto.label = label radio_proto.default = index radio_proto.options[:] = [str(format_func(option)) for option in opt] radio_proto.form_id = current_form_id(self.dg) if help is not None: radio_proto.help = dedent(help) def deserialize_radio(ui_value, widget_id=""): idx = ui_value if ui_value is not None else index return opt[idx] if len(opt) > 0 and opt[idx] is not None else None def serialize_radio(v): if len(options) == 0: return 0 return index_(options, v) current_value, set_frontend_value = register_widget( "radio", radio_proto, user_key=key, on_change_handler=on_change, args=args, kwargs=kwargs, deserializer=deserialize_radio, serializer=serialize_radio, ) if set_frontend_value: radio_proto.value = serialize_radio(current_value) radio_proto.set_value = True self.dg._enqueue("radio", radio_proto) return cast(str, current_value)
def _radio( self, label: str, options: OptionSequence, index: int = 0, format_func: Callable[[Any], Any] = str, key: Optional[Key] = None, help: Optional[str] = None, on_change: Optional[WidgetCallback] = None, args: Optional[WidgetArgs] = None, kwargs: Optional[WidgetKwargs] = None, *, # keyword-only args: disabled: bool = False, ctx: Optional[ScriptRunContext], ) -> Any: key = to_key(key) check_callback_rules(self.dg, on_change) check_session_state_rules(default_value=None if index == 0 else index, key=key) opt = ensure_indexable(options) if not isinstance(index, int): raise StreamlitAPIException("Radio Value has invalid type: %s" % type(index).__name__) if len(opt) > 0 and not 0 <= index < len(opt): raise StreamlitAPIException( "Radio index must be between 0 and length of options") radio_proto = RadioProto() radio_proto.label = label radio_proto.default = index radio_proto.options[:] = [str(format_func(option)) for option in opt] radio_proto.form_id = current_form_id(self.dg) radio_proto.disabled = disabled if help is not None: radio_proto.help = dedent(help) def deserialize_radio(ui_value, widget_id=""): idx = ui_value if ui_value is not None else index return opt[idx] if len(opt) > 0 and opt[idx] is not None else None def serialize_radio(v): if len(options) == 0: return 0 return index_(options, v) current_value, set_frontend_value = register_widget( "radio", radio_proto, user_key=key, on_change_handler=on_change, args=args, kwargs=kwargs, deserializer=deserialize_radio, serializer=serialize_radio, ctx=ctx, ) if set_frontend_value: radio_proto.value = serialize_radio(current_value) radio_proto.set_value = True self.dg._enqueue("radio", radio_proto) return cast(str, current_value)
def _select_slider( self, label: str, options: OptionSequence = [], value: Any = None, format_func: Callable[[Any], Any] = str, key: Optional[Key] = None, help: Optional[str] = None, on_change: Optional[WidgetCallback] = None, args: Optional[WidgetArgs] = None, kwargs: Optional[WidgetKwargs] = None, disabled: bool = False, ctx: Optional[ScriptRunContext] = None, ) -> Any: key = to_key(key) check_callback_rules(self.dg, on_change) check_session_state_rules(default_value=value, key=key) opt = ensure_indexable(options) if len(opt) == 0: raise StreamlitAPIException( "The `options` argument needs to be non-empty") is_range_value = isinstance(value, (list, tuple)) def as_index_list(v): is_range_value = isinstance(v, (list, tuple)) if is_range_value: slider_value = [index_(opt, val) for val in v] start, end = slider_value if start > end: slider_value = [end, start] return slider_value else: # Simplify future logic by always making value a list try: return [index_(opt, v)] except ValueError: if value is not None: raise return [0] # Convert element to index of the elements slider_value = as_index_list(value) slider_proto = SliderProto() slider_proto.label = label slider_proto.format = "%s" slider_proto.default[:] = slider_value slider_proto.min = 0 slider_proto.max = len(opt) - 1 slider_proto.step = 1 # default for index changes slider_proto.data_type = SliderProto.INT slider_proto.options[:] = [str(format_func(option)) for option in opt] slider_proto.form_id = current_form_id(self.dg) slider_proto.disabled = disabled if help is not None: slider_proto.help = dedent(help) def deserialize_select_slider(ui_value, widget_id=""): if not ui_value: # Widget has not been used; fallback to the original value, ui_value = slider_value # The widget always returns floats, so convert to ints before indexing return_value = list(map(lambda x: opt[int(x)], ui_value)) # type: ignore[no-any-return] # If the original value was a list/tuple, so will be the output (and vice versa) return tuple(return_value) if is_range_value else return_value[0] def serialize_select_slider(v): return as_index_list(v) current_value, set_frontend_value = register_widget( "slider", slider_proto, user_key=key, on_change_handler=on_change, args=args, kwargs=kwargs, deserializer=deserialize_select_slider, serializer=serialize_select_slider, ctx=ctx, ) if set_frontend_value: slider_proto.value[:] = serialize_select_slider(current_value) slider_proto.set_value = True self.dg._enqueue("slider", slider_proto) return current_value
def select_slider( self, label: str, options: OptionSequence = [], value=None, format_func=str, key: Optional[Key] = None, help: Optional[str] = None, on_change: Optional[WidgetCallback] = None, args: Optional[WidgetArgs] = None, kwargs: Optional[WidgetKwargs] = None, ): """ Display a slider widget to select items from a list. This also allows you to render a range slider by passing a two-element tuple or list as the `value`. The difference between `st.select_slider` and `st.slider` is that `select_slider` accepts any datatype and takes an iterable set of options, while `slider` only accepts numerical or date/time data and takes a range as input. Parameters ---------- label : str A short label explaining to the user what this slider is for. options : Sequence, numpy.ndarray, pandas.Series, pandas.DataFrame, or pandas.Index Labels for the slider options. All options will be cast to str internally by default. For pandas.DataFrame, the first column is selected. value : a supported type or a tuple/list of supported types or None The value of the slider when it first renders. If a tuple/list of two values is passed here, then a range slider with those lower and upper bounds is rendered. For example, if set to `(1, 10)` the slider will have a selectable range between 1 and 10. Defaults to first option. format_func : function Function to modify the display of the labels from the options. argument. It receives the option as an argument and its output will be cast to str. key : str or int An optional string or integer to use as the unique key for the widget. If this is omitted, a key will be generated for the widget based on its content. Multiple widgets of the same type may not share the same key. help : str An optional tooltip that gets displayed next to the select slider. on_change : callable An optional callback invoked when this select_slider's value changes. args : tuple An optional tuple of args to pass to the callback. kwargs : dict An optional dict of kwargs to pass to the callback. Returns ------- any value or tuple of any value The current value of the slider widget. The return type will match the data type of the value parameter. Examples -------- >>> color = st.select_slider( ... 'Select a color of the rainbow', ... options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']) >>> st.write('My favorite color is', color) And here's an example of a range select slider: >>> start_color, end_color = st.select_slider( ... 'Select a range of color wavelength', ... options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'], ... value=('red', 'blue')) >>> st.write('You selected wavelengths between', start_color, 'and', end_color) """ key = to_key(key) check_callback_rules(self.dg, on_change) check_session_state_rules(default_value=value, key=key) opt = ensure_indexable(options) if len(opt) == 0: raise StreamlitAPIException("The `options` argument needs to be non-empty") is_range_value = isinstance(value, (list, tuple)) def as_index_list(v): is_range_value = isinstance(v, (list, tuple)) if is_range_value: slider_value = [index_(opt, val) for val in v] start, end = slider_value if start > end: slider_value = [end, start] return slider_value else: # Simplify future logic by always making value a list try: return [index_(opt, v)] except ValueError: if value is not None: raise return [0] # Convert element to index of the elements slider_value = as_index_list(value) slider_proto = SliderProto() slider_proto.label = label slider_proto.format = "%s" slider_proto.default[:] = slider_value slider_proto.min = 0 slider_proto.max = len(opt) - 1 slider_proto.step = 1 # default for index changes slider_proto.data_type = SliderProto.INT slider_proto.options[:] = [str(format_func(option)) for option in opt] slider_proto.form_id = current_form_id(self.dg) if help is not None: slider_proto.help = dedent(help) def deserialize_select_slider(ui_value, widget_id=""): if not ui_value: # Widget has not been used; fallback to the original value, ui_value = slider_value # The widget always returns floats, so convert to ints before indexing return_value = list(map(lambda x: opt[int(x)], ui_value)) # type: ignore[no-any-return] # If the original value was a list/tuple, so will be the output (and vice versa) return tuple(return_value) if is_range_value else return_value[0] def serialize_select_slider(v): return as_index_list(v) current_value, set_frontend_value = register_widget( "slider", slider_proto, user_key=key, on_change_handler=on_change, args=args, kwargs=kwargs, deserializer=deserialize_select_slider, serializer=serialize_select_slider, ) if set_frontend_value: slider_proto.value[:] = serialize_select_slider(current_value) slider_proto.set_value = True self.dg._enqueue("slider", slider_proto) return current_value
def selectbox( self, label: str, options: OptionSequence, index: int = 0, format_func: Callable[[Any], str] = str, key: Optional[Key] = None, help: Optional[str] = None, on_change: Optional[WidgetCallback] = None, args: Optional[WidgetArgs] = None, kwargs: Optional[WidgetKwargs] = None, ) -> Any: """Display a select widget. Parameters ---------- label : str A short label explaining to the user what this select widget is for. options : Sequence, numpy.ndarray, pandas.Series, pandas.DataFrame, or pandas.Index Labels for the select options. This will be cast to str internally by default. For pandas.DataFrame, the first column is selected. index : int The index of the preselected option on first render. format_func : function Function to modify the display of the labels. It receives the option as an argument and its output will be cast to str. key : str or int An optional string or integer to use as the unique key for the widget. If this is omitted, a key will be generated for the widget based on its content. Multiple widgets of the same type may not share the same key. help : str An optional tooltip that gets displayed next to the selectbox. on_change : callable An optional callback invoked when this selectbox's value changes. args : tuple An optional tuple of args to pass to the callback. kwargs : dict An optional dict of kwargs to pass to the callback. Returns ------- any The selected option Example ------- >>> option = st.selectbox( ... 'How would you like to be contacted?', ... ('Email', 'Home phone', 'Mobile phone')) >>> >>> st.write('You selected:', option) """ key = to_key(key) check_callback_rules(self.dg, on_change) check_session_state_rules(default_value=None if index == 0 else index, key=key) opt = ensure_indexable(options) if not isinstance(index, int): raise StreamlitAPIException( "Selectbox Value has invalid type: %s" % type(index).__name__) if len(opt) > 0 and not 0 <= index < len(opt): raise StreamlitAPIException( "Selectbox index must be between 0 and length of options") selectbox_proto = SelectboxProto() selectbox_proto.label = label selectbox_proto.default = index selectbox_proto.options[:] = [ str(format_func(option)) for option in opt ] selectbox_proto.form_id = current_form_id(self.dg) if help is not None: selectbox_proto.help = dedent(help) def deserialize_select_box(ui_value, widget_id=""): idx = ui_value if ui_value is not None else index return opt[idx] if len(opt) > 0 and opt[idx] is not None else None def serialize_select_box(v): if len(opt) == 0: return 0 return index_(opt, v) current_value, set_frontend_value = register_widget( "selectbox", selectbox_proto, user_key=key, on_change_handler=on_change, args=args, kwargs=kwargs, deserializer=deserialize_select_box, serializer=serialize_select_box, ) if set_frontend_value: selectbox_proto.value = serialize_select_box(current_value) selectbox_proto.set_value = True self.dg._enqueue("selectbox", selectbox_proto) return cast(str, current_value)
def multiselect( self, label: str, options: OptionSequence, default: Optional[List[str]] = None, format_func=str, key: Optional[Key] = None, help: Optional[str] = None, on_change: Optional[WidgetCallback] = None, args: Optional[WidgetArgs] = None, kwargs: Optional[WidgetKwargs] = None, ) -> List[str]: """Display a multiselect widget. The multiselect widget starts as empty. Parameters ---------- label : str A short label explaining to the user what this select widget is for. options : Sequence, numpy.ndarray, pandas.Series, pandas.DataFrame, or pandas.Index Labels for the select options. This will be cast to str internally by default. For pandas.DataFrame, the first column is selected. default: [str] or None List of default values. format_func : function Function to modify the display of selectbox options. It receives the raw option as an argument and should output the label to be shown for that option. This has no impact on the return value of the selectbox. key : str or int An optional string or integer to use as the unique key for the widget. If this is omitted, a key will be generated for the widget based on its content. Multiple widgets of the same type may not share the same key. help : str An optional tooltip that gets displayed next to the multiselect. on_change : callable An optional callback invoked when this multiselect's value changes. args : tuple An optional tuple of args to pass to the callback. kwargs : dict An optional dict of kwargs to pass to the callback. Returns ------- list A list with the selected options Example ------- >>> options = st.multiselect( ... 'What are your favorite colors', ... ['Green', 'Yellow', 'Red', 'Blue'], ... ['Yellow', 'Red']) >>> >>> st.write('You selected:', options) .. note:: User experience can be degraded for large lists of `options` (100+), as this widget is not designed to handle arbitrary text search efficiently. See this `thread <https://discuss.streamlit.io/t/streamlit-loading-column-data-takes-too-much-time/1791>`_ on the Streamlit community forum for more information and `GitHub issue #1059 <https://github.com/streamlit/streamlit/issues/1059>`_ for updates on the issue. """ key = to_key(key) check_callback_rules(self.dg, on_change) check_session_state_rules(default_value=default, key=key) opt = ensure_indexable(options) # Perform validation checks and return indices base on the default values. def _check_and_convert_to_indices(opt, default_values): if default_values is None and None not in opt: return None if not isinstance(default_values, list): # This if is done before others because calling if not x (done # right below) when x is of type pd.Series() or np.array() throws a # ValueError exception. if is_type(default_values, "numpy.ndarray") or is_type( default_values, "pandas.core.series.Series"): default_values = list(default_values) elif not default_values or default_values in opt: default_values = [default_values] else: default_values = list(default_values) for value in default_values: if value not in opt: raise StreamlitAPIException( "Every Multiselect default value must exist in options" ) return [opt.index(value) for value in default_values] indices = _check_and_convert_to_indices(opt, default) multiselect_proto = MultiSelectProto() multiselect_proto.label = label default_value = [] if indices is None else indices multiselect_proto.default[:] = default_value multiselect_proto.options[:] = [ str(format_func(option)) for option in opt ] multiselect_proto.form_id = current_form_id(self.dg) if help is not None: multiselect_proto.help = dedent(help) def deserialize_multiselect(ui_value: Optional[List[int]], widget_id: str = "") -> List[str]: current_value = ui_value if ui_value is not None else default_value return [opt[i] for i in current_value] def serialize_multiselect(value): return _check_and_convert_to_indices(opt, value) current_value, set_frontend_value = register_widget( "multiselect", multiselect_proto, user_key=key, on_change_handler=on_change, args=args, kwargs=kwargs, deserializer=deserialize_multiselect, serializer=serialize_multiselect, ) if set_frontend_value: multiselect_proto.value[:] = _check_and_convert_to_indices( opt, current_value) multiselect_proto.set_value = True self.dg._enqueue("multiselect", multiselect_proto) return cast(List[str], current_value)
def _selectbox( self, label: str, options: OptionSequence, index: int = 0, format_func: Callable[[Any], Any] = str, key: Optional[Key] = None, help: Optional[str] = None, on_change: Optional[WidgetCallback] = None, args: Optional[WidgetArgs] = None, kwargs: Optional[WidgetKwargs] = None, *, # keyword-only arguments: disabled: bool = False, ctx: Optional[ScriptRunContext] = None, ) -> Any: key = to_key(key) check_callback_rules(self.dg, on_change) check_session_state_rules(default_value=None if index == 0 else index, key=key) opt = ensure_indexable(options) if not isinstance(index, int): raise StreamlitAPIException( "Selectbox Value has invalid type: %s" % type(index).__name__) if len(opt) > 0 and not 0 <= index < len(opt): raise StreamlitAPIException( "Selectbox index must be between 0 and length of options") selectbox_proto = SelectboxProto() selectbox_proto.label = label selectbox_proto.default = index selectbox_proto.options[:] = [ str(format_func(option)) for option in opt ] selectbox_proto.form_id = current_form_id(self.dg) if help is not None: selectbox_proto.help = dedent(help) def deserialize_select_box(ui_value, widget_id=""): idx = ui_value if ui_value is not None else index return opt[idx] if len(opt) > 0 and opt[idx] is not None else None def serialize_select_box(v): if len(opt) == 0: return 0 return index_(opt, v) current_value, set_frontend_value = register_widget( "selectbox", selectbox_proto, user_key=key, on_change_handler=on_change, args=args, kwargs=kwargs, deserializer=deserialize_select_box, serializer=serialize_select_box, ctx=ctx, ) # This needs to be done after register_widget because we don't want # the following proto fields to affect a widget's ID. selectbox_proto.disabled = disabled if set_frontend_value: selectbox_proto.value = serialize_select_box(current_value) selectbox_proto.set_value = True self.dg._enqueue("selectbox", selectbox_proto) return cast(str, current_value)