streamlit-nightly 1.53.2.dev20260131__py3-none-any.whl → 1.53.2.dev20260203__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- streamlit/commands/execution_control.py +2 -2
- streamlit/commands/logo.py +6 -10
- streamlit/components/v2/component_path_utils.py +17 -29
- streamlit/config.py +4 -2
- streamlit/delta_generator.py +2 -0
- streamlit/elements/lib/column_types.py +6 -2
- streamlit/elements/lib/utils.py +6 -6
- streamlit/elements/markdown.py +0 -1
- streamlit/elements/metric.py +2 -1
- streamlit/elements/widgets/button_group.py +6 -276
- streamlit/elements/widgets/feedback.py +322 -0
- streamlit/elements/widgets/number_input.py +2 -1
- streamlit/elements/widgets/slider.py +2 -1
- streamlit/material_icon_names.py +1 -1
- streamlit/path_security.py +98 -0
- streamlit/proto/AudioInput_pb2.py +4 -4
- streamlit/proto/AudioInput_pb2.pyi +3 -3
- streamlit/proto/Audio_pb2.py +2 -2
- streamlit/proto/BackMsg_pb2.pyi +2 -10
- streamlit/proto/Balloons_pb2.pyi +0 -2
- streamlit/proto/Block_pb2.py +35 -35
- streamlit/proto/ButtonGroup_pb2.py +10 -12
- streamlit/proto/ButtonGroup_pb2.pyi +6 -41
- streamlit/proto/Button_pb2.py +2 -2
- streamlit/proto/CameraInput_pb2.py +4 -4
- streamlit/proto/CameraInput_pb2.pyi +3 -3
- streamlit/proto/ChatInput_pb2.py +2 -2
- streamlit/proto/Checkbox_pb2.py +6 -6
- streamlit/proto/Checkbox_pb2.pyi +3 -3
- streamlit/proto/Code_pb2.py +2 -2
- streamlit/proto/ColorPicker_pb2.py +4 -4
- streamlit/proto/ColorPicker_pb2.pyi +3 -3
- streamlit/proto/Common_pb2.py +6 -6
- streamlit/proto/DateInput_pb2.py +4 -4
- streamlit/proto/DateInput_pb2.pyi +3 -3
- streamlit/proto/DateTimeInput_pb2.py +4 -4
- streamlit/proto/DateTimeInput_pb2.pyi +3 -3
- streamlit/proto/DeckGlJsonChart_pb2.py +2 -2
- streamlit/proto/Delta_pb2.py +2 -2
- streamlit/proto/DocString_pb2.py +1 -1
- streamlit/proto/Element_pb2.py +4 -4
- streamlit/proto/Element_pb2.pyi +9 -9
- streamlit/proto/Feedback_pb2.py +28 -0
- streamlit/proto/Feedback_pb2.pyi +93 -0
- streamlit/proto/FileUploader_pb2.py +4 -4
- streamlit/proto/FileUploader_pb2.pyi +3 -3
- streamlit/proto/ForwardMsg_pb2.py +8 -8
- streamlit/proto/GraphVizChart_pb2.py +2 -2
- streamlit/proto/IFrame_pb2.py +3 -3
- streamlit/proto/Image_pb2.py +4 -4
- streamlit/proto/Image_pb2.pyi +1 -7
- streamlit/proto/{BokehChart_pb2.py → LabelVisibility_pb2.py} +7 -5
- streamlit/proto/{LabelVisibilityMessage_pb2.pyi → LabelVisibility_pb2.pyi} +14 -14
- streamlit/proto/Markdown_pb2.py +4 -4
- streamlit/proto/Markdown_pb2.pyi +1 -5
- streamlit/proto/Metric_pb2.py +10 -10
- streamlit/proto/Metric_pb2.pyi +3 -3
- streamlit/proto/MultiSelect_pb2.py +4 -4
- streamlit/proto/MultiSelect_pb2.pyi +3 -3
- streamlit/proto/NewSession_pb2.py +38 -26
- streamlit/proto/NewSession_pb2.pyi +42 -8
- streamlit/proto/NumberInput_pb2.py +6 -6
- streamlit/proto/NumberInput_pb2.pyi +3 -3
- streamlit/proto/PlotlyChart_pb2.py +2 -2
- streamlit/proto/Radio_pb2.py +4 -4
- streamlit/proto/Radio_pb2.pyi +3 -3
- streamlit/proto/Selectbox_pb2.py +4 -4
- streamlit/proto/Selectbox_pb2.pyi +3 -6
- streamlit/proto/Slider_pb2.py +8 -8
- streamlit/proto/Slider_pb2.pyi +3 -3
- streamlit/proto/Snow_pb2.pyi +0 -2
- streamlit/proto/TextArea_pb2.py +4 -4
- streamlit/proto/TextArea_pb2.pyi +3 -3
- streamlit/proto/TextInput_pb2.py +6 -6
- streamlit/proto/TextInput_pb2.pyi +3 -3
- streamlit/proto/TimeInput_pb2.py +4 -4
- streamlit/proto/TimeInput_pb2.pyi +3 -3
- streamlit/proto/Video_pb2.py +2 -2
- streamlit/runtime/app_session.py +9 -1
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +325 -310
- streamlit/static/static/css/{index.BUP6fTcR.css → index.C8MrxwGF.css} +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.DC6KVDKK.js → ErrorOutline.esm.C9uHPmIj.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.Z9hRQIHi.js → FileDownload.esm.D-YPxF3t.js} +1 -1
- streamlit/static/static/js/{FileHelper.DqvW90pm.js → FileHelper.DQSH0zYW.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.DTFnX0js.js → FormClearHelper.DQoXcOWo.js} +1 -1
- streamlit/static/static/js/{InputInstructions.CdzsN_Va.js → InputInstructions.C7VMyGT7.js} +1 -1
- streamlit/static/static/js/{Particles.12xFSjcn.js → Particles.BdQSRZde.js} +1 -1
- streamlit/static/static/js/{ProgressBar.Dg-oMbWg.js → ProgressBar.DNF_pWKr.js} +2 -2
- streamlit/static/static/js/{StreamlitSyntaxHighlighter.rbzmcipw.js → StreamlitSyntaxHighlighter.Cys9Bt18.js} +2 -2
- streamlit/static/static/js/{TableChart.esm.CzJtGIR-.js → TableChart.esm.B9SMgSK4.js} +1 -1
- streamlit/static/static/js/{Toolbar.COH7NaOE.js → Toolbar.BXfC9Z-W.js} +1 -1
- streamlit/static/static/js/{WidgetLabelHelpIconInline.Dlc8f0Ji.js → WidgetLabelHelpIconInline.gkreC55g.js} +1 -1
- streamlit/static/static/js/{base-input.Q-zJLgRK.js → base-input.iB32RS3w.js} +4 -4
- streamlit/static/static/js/{checkbox.BKgWNdeI.js → checkbox.Bqz68SYq.js} +1 -1
- streamlit/static/static/js/{createDownloadLinkElement.6oO-YlYv.js → createDownloadLinkElement.YxVC9Qur.js} +1 -1
- streamlit/static/static/js/data-grid-overlay-editor.sBsdk5Xg.js +1 -0
- streamlit/static/static/js/{downloader.BBXcXdX1.js → downloader.Bzxqt3AW.js} +1 -1
- streamlit/static/static/js/{embed.CJzOXYBF.js → embed.CDzakah3.js} +1 -1
- streamlit/static/static/js/{es6.CdxPQzwJ.js → es6.CxCc4bfn.js} +2 -2
- streamlit/static/static/js/formatNumber.L8T7D36k.js +1 -0
- streamlit/static/static/js/{iconPosition.BVScIr6G.js → iconPosition.C47DkA-1.js} +1 -1
- streamlit/static/static/js/{iframeResizer.contentWindow.D_QHVqPM.js → iframeResizer.contentWindow.uEFLXEg3.js} +1 -1
- streamlit/static/static/js/{index.CvtybR-u.js → index.B3zULhHv.js} +1 -1
- streamlit/static/static/js/{index.DAyGxxdm.js → index.B60AZFRh.js} +3 -3
- streamlit/static/static/js/{index.BED2_zc7.js → index.BG4RxMOI.js} +1 -1
- streamlit/static/static/js/{index.CPc_uZux.js → index.BHyzKS4e.js} +45 -45
- streamlit/static/static/js/{index.Dud7RRHc.js → index.BVTW_o-a.js} +1 -1
- streamlit/static/static/js/{index.BQnLeHnr.js → index.BV_YgIHe.js} +3 -3
- streamlit/static/static/js/index.B_LfkwqU.js +2 -0
- streamlit/static/static/js/{index.DCe7fo-m.js → index.Ba8L-ulI.js} +1 -1
- streamlit/static/static/js/{index.DAfIQKfP.js → index.Bh5BZaHG.js} +2 -2
- streamlit/static/static/js/{index.DU68jVpM.js → index.Bnwh8oZr.js} +16 -16
- streamlit/static/static/js/index.BrZtYm2A.js +2 -0
- streamlit/static/static/js/index.BsrhCS7f.js +1 -0
- streamlit/static/static/js/{index.CxoREvnF.js → index.BuJPJSD7.js} +2 -2
- streamlit/static/static/js/{index.6DFY6LUF.js → index.BvHsyiyy.js} +1 -1
- streamlit/static/static/js/{index.Biyf9aUg.js → index.BwTkGOAy.js} +2 -2
- streamlit/static/static/js/{index.DNfyKqhQ.js → index.BwvxzVOo.js} +1 -1
- streamlit/static/static/js/{index.iXh5nbLZ.js → index.BzdcdLDK.js} +1 -1
- streamlit/static/static/js/{index.YULCxEtm.js → index.C1d2QjTR.js} +1 -1
- streamlit/static/static/js/index.C1uZrWog.js +1 -0
- streamlit/static/static/js/{index.C5oqIM3a.js → index.C5-TpWis.js} +1 -1
- streamlit/static/static/js/{index.D6OexhdL.js → index.C6dhwBSe.js} +1 -1
- streamlit/static/static/js/{index.y-pa6LIX.js → index.CAbQaUvi.js} +1 -1
- streamlit/static/static/js/{index.BSpYHDvk.js → index.CAbafj7s.js} +1 -1
- streamlit/static/static/js/{index.BDtN2n7T.js → index.CCLteRW6.js} +1 -1
- streamlit/static/static/js/{index.mSdC1FV6.js → index.CQ713nQM.js} +1 -1
- streamlit/static/static/js/index.CcBYyLfq.js +2 -0
- streamlit/static/static/js/{index.CBE2cIbj.js → index.CjBDVb1a.js} +1 -1
- streamlit/static/static/js/{index.BxQxTpWl.js → index.Ck0ZkOfK.js} +1 -1
- streamlit/static/static/js/{index.B80gSxrS.js → index.CzwJzgQs.js} +1 -1
- streamlit/static/static/js/{index.DyfvmNCy.js → index.D-9VyyiA.js} +1 -1
- streamlit/static/static/js/{index.nL1fkE1D.js → index.D2R3Co5f.js} +1 -1
- streamlit/static/static/js/{index.DZmBuE3z.js → index.D7L9gHlE.js} +3 -3
- streamlit/static/static/js/{index.BqxwnMem.js → index.DEKnCsY-.js} +2 -2
- streamlit/static/static/js/{index.D9v2Y8Gk.js → index.DHrByikW.js} +1 -1
- streamlit/static/static/js/index.DN_oudQl.js +1 -0
- streamlit/static/static/js/{index.DrcbvB2t.js → index.DO55kRo5.js} +1 -1
- streamlit/static/static/js/{index.BqbKiDp2.js → index.D_cvtSlg.js} +1 -1
- streamlit/static/static/js/{index.CrY1BsL3.js → index.DgqmsDCJ.js} +1 -1
- streamlit/static/static/js/{index.BtOoVQt7.js → index.DjgdCvlK.js} +1 -1
- streamlit/static/static/js/{index.BxMkW82k.js → index.DqhZqWYB.js} +1 -1
- streamlit/static/static/js/{index.bQJYmJ2T.js → index.Dtbj_oyb.js} +1 -1
- streamlit/static/static/js/{index.CUYi3FrD.js → index.QXukCzoh.js} +1 -1
- streamlit/static/static/js/{index.BiCbrx53.js → index.XJY9qZ6a.js} +1 -1
- streamlit/static/static/js/{index.GieKl4BG.js → index.aZRhdEuX.js} +1 -1
- streamlit/static/static/js/{index._1zqETQ9.js → index.fUsWkW8E.js} +1 -1
- streamlit/static/static/js/index.h2N-W51I.js +11 -0
- streamlit/static/static/js/index.iUHLeAvv.js +1 -0
- streamlit/static/static/js/{index.DRoJNzFX.js → index.kBgXO7Vv.js} +1 -1
- streamlit/static/static/js/{index.BSYebegS.js → index.kEL0HsUR.js} +1 -1
- streamlit/static/static/js/index.w7yKy9fh.js +6 -0
- streamlit/static/static/js/{input.BcC6sPE_.js → input.BCHJn1Cw.js} +1 -1
- streamlit/static/static/js/{main.TU5_aabd.js → main.23ZP6f1E.js} +1 -1
- streamlit/static/static/js/{memory.By_OTlI4.js → memory.D8f8Q4mO.js} +1 -1
- streamlit/static/static/js/number-overlay-editor.ZWvSpjJ5.js +9 -0
- streamlit/static/static/js/{pandasStylerUtils.3IiIKU9-.js → pandasStylerUtils.DlZ2GBs_.js} +1 -1
- streamlit/static/static/js/{sandbox.DnxTbWzV.js → sandbox.BH6D3KL9.js} +1 -1
- streamlit/static/static/js/sprintfjs.CtrdaGLQ.js +1 -0
- streamlit/static/static/js/{styled-components.BeEcZ0vW.js → styled-components.iD1HRMLc.js} +1 -1
- streamlit/static/static/js/{throttle.emUyC44c.js → throttle.DR7d9vp_.js} +1 -1
- streamlit/static/static/js/{timepicker.DZ_ZufYF.js → timepicker.Bd34xjcG.js} +4 -4
- streamlit/static/static/js/{toConsumableArray.DDV1bN1-.js → toConsumableArray.BDTTq1c5.js} +2 -2
- streamlit/static/static/js/uniqueId.Bd_Iuzvc.js +1 -0
- streamlit/static/static/js/useBasicWidgetState.BXKaD8DQ.js +1 -0
- streamlit/static/static/js/{useIntlLocale.BBDLbTq9.js → useIntlLocale.CysOvegI.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.BIApLJKn.js → useTextInputAutoExpand.CVd5Hf2S.js} +1 -1
- streamlit/static/static/js/{useUpdateUiValue.DQ4RuJNC.js → useUpdateUiValue.CIUgfO8X.js} +1 -1
- streamlit/static/static/js/{useWaveformController.B0olyXLQ.js → useWaveformController.CDLqlnLv.js} +1 -1
- streamlit/static/static/js/{withCalculatedWidth.DYeqePuh.js → withCalculatedWidth.Ce1Zblb2.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.DtkUCO_d.js → withFullScreenWrapper.DBm7N75M.js} +1 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.CnH1S47a.woff2 +0 -0
- streamlit/testing/v1/app_test.py +21 -5
- streamlit/testing/v1/element_tree.py +65 -2
- streamlit/web/server/app_static_file_handler.py +9 -0
- streamlit/web/server/bidi_component_request_handler.py +4 -4
- streamlit/web/server/component_file_utils.py +14 -6
- streamlit/web/server/component_request_handler.py +2 -2
- streamlit/web/server/starlette/starlette_app.py +7 -1
- streamlit/web/server/starlette/starlette_path_security_middleware.py +97 -0
- streamlit/web/server/starlette/starlette_routes.py +6 -3
- streamlit/web/server/starlette/starlette_static_routes.py +14 -4
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/RECORD +188 -184
- streamlit/proto/BokehChart_pb2.pyi +0 -56
- streamlit/proto/LabelVisibilityMessage_pb2.py +0 -28
- streamlit/static/static/js/data-grid-overlay-editor.CO0xdNiG.js +0 -1
- streamlit/static/static/js/formatNumber.DB5irY8c.js +0 -1
- streamlit/static/static/js/index.BBTKOM0z.js +0 -6
- streamlit/static/static/js/index.CE2WIFD1.js +0 -2
- streamlit/static/static/js/index.Cpu2p5bH.js +0 -1
- streamlit/static/static/js/index.CtbETWQK.js +0 -2
- streamlit/static/static/js/index.DAnczAW2.js +0 -2
- streamlit/static/static/js/index.DhRAGiPR.js +0 -1
- streamlit/static/static/js/index.DyXcT2tD.js +0 -11
- streamlit/static/static/js/index.tuFFlbxa.js +0 -1
- streamlit/static/static/js/number-overlay-editor.FSRaRpbU.js +0 -9
- streamlit/static/static/js/sprintf.DpPCfzXw.js +0 -1
- streamlit/static/static/js/uniqueId.DTwvAE-J.js +0 -1
- streamlit/static/static/js/useBasicWidgetState.DvpdEDYZ.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/top_level.txt +0 -0
|
@@ -133,7 +133,7 @@ def _set_query_params_for_switch(
|
|
|
133
133
|
def rerun( # type: ignore[misc]
|
|
134
134
|
*, # The scope argument can only be passed via keyword.
|
|
135
135
|
scope: Literal["app", "fragment"] = "app",
|
|
136
|
-
) -> NoReturn: # ty: ignore[
|
|
136
|
+
) -> NoReturn: # ty: ignore[empty-body]
|
|
137
137
|
"""Rerun the script immediately.
|
|
138
138
|
|
|
139
139
|
When ``st.rerun()`` is called, Streamlit halts the current script run and
|
|
@@ -189,7 +189,7 @@ def switch_page( # type: ignore[misc]
|
|
|
189
189
|
page: str | Path | StreamlitPage,
|
|
190
190
|
*,
|
|
191
191
|
query_params: QueryParamsInput | None = None,
|
|
192
|
-
) -> NoReturn: # ty: ignore[
|
|
192
|
+
) -> NoReturn: # ty: ignore[empty-body]
|
|
193
193
|
"""Programmatically switch the current page in a multipage app.
|
|
194
194
|
|
|
195
195
|
When ``st.switch_page`` is called, the current page execution stops and
|
streamlit/commands/logo.py
CHANGED
|
@@ -108,13 +108,13 @@ def logo(
|
|
|
108
108
|
|
|
109
109
|
Parameters
|
|
110
110
|
----------
|
|
111
|
-
image: Anything supported by st.image (except list)
|
|
111
|
+
image: Anything supported by st.image (except list) or str
|
|
112
112
|
The image to display in the upper-left corner of your app and its
|
|
113
113
|
sidebar. If ``icon_image`` is also provided, then Streamlit will only
|
|
114
114
|
display ``image`` in the sidebar.
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
the following strings are valid:
|
|
116
|
+
``image`` can be any of the types supported by |st.image|_ except
|
|
117
|
+
a list. Additionally, the following strings are valid:
|
|
118
118
|
|
|
119
119
|
- A single-character emoji. For example, you can set ``image="🏠"``
|
|
120
120
|
or ``image="🚀"``. Emoji short codes are not supported.
|
|
@@ -146,19 +146,15 @@ def logo(
|
|
|
146
146
|
The external URL to open when a user clicks on the logo. The URL must
|
|
147
147
|
start with "\http://" or "\https://". If ``link`` is ``None`` (default),
|
|
148
148
|
the logo will not include a hyperlink.
|
|
149
|
-
icon_image: Anything supported by st.image (except list),
|
|
149
|
+
icon_image: Anything supported by st.image (except list), str, or None
|
|
150
150
|
An optional, typically smaller image to replace ``image`` in the
|
|
151
|
-
upper-left corner when the sidebar is closed.
|
|
151
|
+
upper-left corner when the sidebar is closed. This can be any of the
|
|
152
|
+
types allowed for the ``image`` parameter. If ``icon_image`` is
|
|
152
153
|
``None`` (default), Streamlit will always display ``image`` in the
|
|
153
154
|
upper-left corner, regardless of whether the sidebar is open or closed.
|
|
154
155
|
Otherwise, Streamlit will render ``icon_image`` in the upper-left
|
|
155
156
|
corner of the app when the sidebar is closed.
|
|
156
157
|
|
|
157
|
-
In addition to any of the types supported by ``st.image`` (except list),
|
|
158
|
-
this also accepts single-character emojis (e.g., ``"🏠"``) and Material
|
|
159
|
-
icons (e.g., ``":material/home:"``). See the ``image`` parameter for
|
|
160
|
-
more details on these formats.
|
|
161
|
-
|
|
162
158
|
Streamlit scales the image to a max height set by ``size`` and a max
|
|
163
159
|
width to fit within the sidebar. If the sidebar is closed, the max
|
|
164
160
|
width is retained from when it was last open.
|
|
@@ -22,12 +22,12 @@ outside of a declared package root.
|
|
|
22
22
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
|
-
import os
|
|
26
25
|
from pathlib import Path
|
|
27
26
|
from typing import Final
|
|
28
27
|
|
|
29
28
|
from streamlit.errors import StreamlitComponentRegistryError
|
|
30
29
|
from streamlit.logger import get_logger
|
|
30
|
+
from streamlit.path_security import is_unsafe_path_pattern
|
|
31
31
|
|
|
32
32
|
_LOGGER: Final = get_logger(__name__)
|
|
33
33
|
|
|
@@ -132,7 +132,12 @@ class ComponentPathUtils:
|
|
|
132
132
|
|
|
133
133
|
@staticmethod
|
|
134
134
|
def _assert_relative_no_traversal(path: str, *, label: str) -> None:
|
|
135
|
-
"""Raise if ``path`` is absolute or
|
|
135
|
+
"""Raise if ``path`` is absolute, contains traversal, or has unsafe patterns.
|
|
136
|
+
|
|
137
|
+
This method uses the shared ``is_unsafe_path_pattern`` function to ensure
|
|
138
|
+
consistent security checks across the codebase. The shared function also
|
|
139
|
+
checks for additional patterns like null bytes, forward-slash UNC paths,
|
|
140
|
+
and drive-relative paths (e.g., ``C:foo``).
|
|
136
141
|
|
|
137
142
|
Parameters
|
|
138
143
|
----------
|
|
@@ -141,34 +146,17 @@ class ComponentPathUtils:
|
|
|
141
146
|
label : str
|
|
142
147
|
Human-readable label used in error messages (e.g., "component paths").
|
|
143
148
|
"""
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
# Consider rooted backslash paths "\\dir" as absolute on Windows-like inputs
|
|
154
|
-
is_rooted_backslash = path.startswith("\\") and not is_unc_abs
|
|
155
|
-
|
|
156
|
-
if (
|
|
157
|
-
os.path.isabs(path)
|
|
158
|
-
or is_windows_drive_abs
|
|
159
|
-
or is_unc_abs
|
|
160
|
-
or is_rooted_backslash
|
|
161
|
-
):
|
|
162
|
-
raise StreamlitComponentRegistryError(
|
|
163
|
-
f"Absolute paths are not allowed in {label}: {path}"
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
# Segment-based traversal detection to avoid false positives (e.g. "file..js")
|
|
167
|
-
normalized = path.replace("\\", "/")
|
|
168
|
-
segments = [seg for seg in normalized.split("/") if seg != ""]
|
|
169
|
-
if any(seg == ".." for seg in segments):
|
|
149
|
+
if is_unsafe_path_pattern(path):
|
|
150
|
+
# Determine appropriate error message based on pattern.
|
|
151
|
+
# Use segment-based check to avoid false positives like "file..js"
|
|
152
|
+
normalized = path.replace("\\", "/")
|
|
153
|
+
segments = [seg for seg in normalized.split("/") if seg]
|
|
154
|
+
if ".." in segments:
|
|
155
|
+
raise StreamlitComponentRegistryError(
|
|
156
|
+
f"Path traversal attempts are not allowed in {label}: {path}"
|
|
157
|
+
)
|
|
170
158
|
raise StreamlitComponentRegistryError(
|
|
171
|
-
f"
|
|
159
|
+
f"Unsafe paths are not allowed in {label}: {path}"
|
|
172
160
|
)
|
|
173
161
|
|
|
174
162
|
@staticmethod
|
streamlit/config.py
CHANGED
|
@@ -621,8 +621,10 @@ _create_option(
|
|
|
621
621
|
"client.showErrorLinks",
|
|
622
622
|
description="""
|
|
623
623
|
Controls whether to show external help links (Google, ChatGPT) in
|
|
624
|
-
error displays.
|
|
625
|
-
|
|
624
|
+
error displays. The following values are valid:
|
|
625
|
+
- "auto" (default): Links are shown only on localhost.
|
|
626
|
+
- True: Links are shown on all domains.
|
|
627
|
+
- False: Links are never shown.
|
|
626
628
|
""",
|
|
627
629
|
default_val="auto",
|
|
628
630
|
type_=str,
|
streamlit/delta_generator.py
CHANGED
|
@@ -91,6 +91,7 @@ from streamlit.elements.widgets.chat import ChatMixin
|
|
|
91
91
|
from streamlit.elements.widgets.checkbox import CheckboxMixin
|
|
92
92
|
from streamlit.elements.widgets.color_picker import ColorPickerMixin
|
|
93
93
|
from streamlit.elements.widgets.data_editor import DataEditorMixin
|
|
94
|
+
from streamlit.elements.widgets.feedback import FeedbackMixin
|
|
94
95
|
from streamlit.elements.widgets.file_uploader import FileUploaderMixin
|
|
95
96
|
from streamlit.elements.widgets.multiselect import MultiSelectMixin
|
|
96
97
|
from streamlit.elements.widgets.number_input import NumberInputMixin
|
|
@@ -189,6 +190,7 @@ class DeltaGenerator(
|
|
|
189
190
|
ColorPickerMixin,
|
|
190
191
|
EmptyMixin,
|
|
191
192
|
ExceptionMixin,
|
|
193
|
+
FeedbackMixin,
|
|
192
194
|
FileUploaderMixin,
|
|
193
195
|
FormMixin,
|
|
194
196
|
GraphvizMixin,
|
|
@@ -529,7 +529,9 @@ def NumberColumn(
|
|
|
529
529
|
specifier, like ``"%d"`` to show a signed integer (e.g. "1234") or
|
|
530
530
|
``"%X"`` to show an unsigned hexadecimal integer (e.g. "4D2"). You
|
|
531
531
|
can also add prefixes and suffixes. To show British pounds, use
|
|
532
|
-
``"£ %.2f"`` (e.g. "£ 1234.57").
|
|
532
|
+
``"£ %.2f"`` (e.g. "£ 1234.57"). Use ``,`` for thousand separators
|
|
533
|
+
(e.g. ``"%,d"`` yields ``"1,234"``). For more information, see
|
|
534
|
+
`sprintf-js
|
|
533
535
|
<https://github.com/alexei/sprintf.js?tab=readme-ov-file#format-specification>`_.
|
|
534
536
|
|
|
535
537
|
Formatting from ``column_config`` always takes precedence over
|
|
@@ -2517,7 +2519,9 @@ def ProgressColumn(
|
|
|
2517
2519
|
specifier, like ``"%d"`` to show a signed integer (e.g. "1234") or
|
|
2518
2520
|
``"%X"`` to show an unsigned hexadecimal integer (e.g. "4D2"). You
|
|
2519
2521
|
can also add prefixes and suffixes. To show British pounds, use
|
|
2520
|
-
``"£ %.2f"`` (e.g. "£ 1234.57").
|
|
2522
|
+
``"£ %.2f"`` (e.g. "£ 1234.57"). Use ``,`` for thousand separators
|
|
2523
|
+
(e.g. ``"%,d"`` yields ``"1,234"``). For more information, see
|
|
2524
|
+
`sprintf-js
|
|
2521
2525
|
<https://github.com/alexei/sprintf.js?tab=readme-ov-file#format-specification>`_.
|
|
2522
2526
|
|
|
2523
2527
|
Number formatting from ``column_config`` always takes precedence over
|
streamlit/elements/lib/utils.py
CHANGED
|
@@ -31,7 +31,7 @@ from streamlit import config
|
|
|
31
31
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
32
32
|
from streamlit.errors import StreamlitDuplicateElementId, StreamlitDuplicateElementKey
|
|
33
33
|
from streamlit.proto.ChatInput_pb2 import ChatInput
|
|
34
|
-
from streamlit.proto.
|
|
34
|
+
from streamlit.proto.LabelVisibility_pb2 import LabelVisibility as LabelVisibilityProto
|
|
35
35
|
from streamlit.runtime.scriptrunner_utils.script_run_context import (
|
|
36
36
|
ScriptRunContext,
|
|
37
37
|
get_script_run_ctx,
|
|
@@ -68,15 +68,15 @@ SAFE_VALUES: TypeAlias = Union[
|
|
|
68
68
|
|
|
69
69
|
def get_label_visibility_proto_value(
|
|
70
70
|
label_visibility_string: LabelVisibility,
|
|
71
|
-
) ->
|
|
72
|
-
"""Returns one of
|
|
71
|
+
) -> LabelVisibilityProto.LabelVisibilityOptions.ValueType:
|
|
72
|
+
"""Returns one of LabelVisibilityProto enum constants based on string value."""
|
|
73
73
|
|
|
74
74
|
if label_visibility_string == "visible":
|
|
75
|
-
return
|
|
75
|
+
return LabelVisibilityProto.LabelVisibilityOptions.VISIBLE
|
|
76
76
|
if label_visibility_string == "hidden":
|
|
77
|
-
return
|
|
77
|
+
return LabelVisibilityProto.LabelVisibilityOptions.HIDDEN
|
|
78
78
|
if label_visibility_string == "collapsed":
|
|
79
|
-
return
|
|
79
|
+
return LabelVisibilityProto.LabelVisibilityOptions.COLLAPSED
|
|
80
80
|
|
|
81
81
|
raise ValueError(f"Unknown label visibility value: {label_visibility_string}")
|
|
82
82
|
|
streamlit/elements/markdown.py
CHANGED
|
@@ -270,7 +270,6 @@ class MarkdownMixin:
|
|
|
270
270
|
caption_proto = MarkdownProto()
|
|
271
271
|
caption_proto.body = clean_text(body)
|
|
272
272
|
caption_proto.allow_html = unsafe_allow_html
|
|
273
|
-
caption_proto.is_caption = True
|
|
274
273
|
caption_proto.element_type = MarkdownProto.Type.CAPTION
|
|
275
274
|
if help:
|
|
276
275
|
caption_proto.help = help
|
streamlit/elements/metric.py
CHANGED
|
@@ -259,7 +259,8 @@ class MetricMixin:
|
|
|
259
259
|
- ``"engineering"``: Show the number in engineering notation (e.g. "1.235E3").
|
|
260
260
|
- printf-style format string: Format the number with a printf
|
|
261
261
|
specifier, like ``"%d"`` to show a signed integer (e.g. "1234") or
|
|
262
|
-
``"%.2f"`` to show a float with 2 decimal places.
|
|
262
|
+
``"%.2f"`` to show a float with 2 decimal places. Use ``,`` for
|
|
263
|
+
thousand separators (e.g. ``"%,d"`` yields ``"1,234"``).
|
|
263
264
|
|
|
264
265
|
Examples
|
|
265
266
|
--------
|
|
@@ -19,7 +19,6 @@ from dataclasses import dataclass, field
|
|
|
19
19
|
from typing import (
|
|
20
20
|
TYPE_CHECKING,
|
|
21
21
|
Any,
|
|
22
|
-
Final,
|
|
23
22
|
Generic,
|
|
24
23
|
Literal,
|
|
25
24
|
TypeAlias,
|
|
@@ -28,7 +27,6 @@ from typing import (
|
|
|
28
27
|
overload,
|
|
29
28
|
)
|
|
30
29
|
|
|
31
|
-
from streamlit import config
|
|
32
30
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
33
31
|
from streamlit.elements.lib.layout_utils import (
|
|
34
32
|
LayoutConfig,
|
|
@@ -76,20 +74,6 @@ if TYPE_CHECKING:
|
|
|
76
74
|
T = TypeVar("T")
|
|
77
75
|
V = TypeVar("V")
|
|
78
76
|
|
|
79
|
-
_THUMB_ICONS: Final = (":material/thumb_up:", ":material/thumb_down:")
|
|
80
|
-
_FACES_ICONS: Final = (
|
|
81
|
-
":material/sentiment_sad:",
|
|
82
|
-
":material/sentiment_dissatisfied:",
|
|
83
|
-
":material/sentiment_neutral:",
|
|
84
|
-
":material/sentiment_satisfied:",
|
|
85
|
-
":material/sentiment_very_satisfied:",
|
|
86
|
-
)
|
|
87
|
-
_NUMBER_STARS: Final = 5
|
|
88
|
-
_STAR_ICON: Final = ":material/star:"
|
|
89
|
-
# we don't have the filled-material icon library as a dependency. Hence, we have it here
|
|
90
|
-
# in base64 format and send it over the wire as an image.
|
|
91
|
-
_SELECTED_STAR_ICON: Final = ":material/star_filled:"
|
|
92
|
-
|
|
93
77
|
SelectionMode: TypeAlias = Literal["single", "multi"]
|
|
94
78
|
|
|
95
79
|
|
|
@@ -185,35 +169,6 @@ class ButtonGroupSerde(Generic[T]):
|
|
|
185
169
|
return self.serde.deserialize(ui_value)
|
|
186
170
|
|
|
187
171
|
|
|
188
|
-
def get_mapped_options(
|
|
189
|
-
feedback_option: Literal["thumbs", "faces", "stars"],
|
|
190
|
-
) -> tuple[list[ButtonGroupProto.Option], list[int]]:
|
|
191
|
-
# options object understandable by the web app
|
|
192
|
-
options: list[ButtonGroupProto.Option] = []
|
|
193
|
-
# we use the option index in the webapp communication to
|
|
194
|
-
# indicate which option is selected
|
|
195
|
-
options_indices: list[int] = []
|
|
196
|
-
|
|
197
|
-
if feedback_option == "thumbs":
|
|
198
|
-
# reversing the index mapping to have thumbs up first (but still with the higher
|
|
199
|
-
# index (=sentiment) in the list)
|
|
200
|
-
options_indices = list(reversed(range(len(_THUMB_ICONS))))
|
|
201
|
-
options = [ButtonGroupProto.Option(content_icon=icon) for icon in _THUMB_ICONS]
|
|
202
|
-
elif feedback_option == "faces":
|
|
203
|
-
options_indices = list(range(len(_FACES_ICONS)))
|
|
204
|
-
options = [ButtonGroupProto.Option(content_icon=icon) for icon in _FACES_ICONS]
|
|
205
|
-
elif feedback_option == "stars":
|
|
206
|
-
options_indices = list(range(_NUMBER_STARS))
|
|
207
|
-
options = [
|
|
208
|
-
ButtonGroupProto.Option(
|
|
209
|
-
content_icon=_STAR_ICON,
|
|
210
|
-
selected_content_icon=_SELECTED_STAR_ICON,
|
|
211
|
-
)
|
|
212
|
-
] * _NUMBER_STARS
|
|
213
|
-
|
|
214
|
-
return options, options_indices
|
|
215
|
-
|
|
216
|
-
|
|
217
172
|
def _build_proto(
|
|
218
173
|
widget_id: str,
|
|
219
174
|
formatted_options: Sequence[ButtonGroupProto.Option],
|
|
@@ -221,10 +176,7 @@ def _build_proto(
|
|
|
221
176
|
disabled: bool,
|
|
222
177
|
current_form_id: str,
|
|
223
178
|
click_mode: ButtonGroupProto.ClickMode.ValueType,
|
|
224
|
-
|
|
225
|
-
ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
|
|
226
|
-
),
|
|
227
|
-
style: Literal["borderless", "pills", "segmented_control"] = "pills",
|
|
179
|
+
style: Literal["pills", "segmented_control"] = "pills",
|
|
228
180
|
label: str | None = None,
|
|
229
181
|
label_visibility: LabelVisibility = "visible",
|
|
230
182
|
help: str | None = None,
|
|
@@ -249,7 +201,6 @@ def _build_proto(
|
|
|
249
201
|
|
|
250
202
|
for formatted_option in formatted_options:
|
|
251
203
|
proto.options.append(formatted_option)
|
|
252
|
-
proto.selection_visualization = selection_visualization
|
|
253
204
|
return proto
|
|
254
205
|
|
|
255
206
|
|
|
@@ -263,219 +214,6 @@ def _maybe_raise_selection_mode_warning(selection_mode: SelectionMode) -> None:
|
|
|
263
214
|
|
|
264
215
|
|
|
265
216
|
class ButtonGroupMixin:
|
|
266
|
-
# These overloads are not documented in the docstring, at least not at this time, on
|
|
267
|
-
# the theory that most people won't know what it means. And the Literals here are a
|
|
268
|
-
# subclass of int anyway. Usually, we would make a type alias for
|
|
269
|
-
# Literal["thumbs", "faces", "stars"]; but, in this case, we don't use it in too
|
|
270
|
-
# many other places, and it's a more helpful autocomplete if we just enumerate the
|
|
271
|
-
# values explicitly, so a decision has been made to keep it as not an alias.
|
|
272
|
-
@overload
|
|
273
|
-
def feedback(
|
|
274
|
-
self,
|
|
275
|
-
options: Literal["thumbs"] = ...,
|
|
276
|
-
*,
|
|
277
|
-
key: Key | None = None,
|
|
278
|
-
default: int | None = None,
|
|
279
|
-
disabled: bool = False,
|
|
280
|
-
on_change: WidgetCallback | None = None,
|
|
281
|
-
args: WidgetArgs | None = None,
|
|
282
|
-
kwargs: WidgetKwargs | None = None,
|
|
283
|
-
width: Width = "content",
|
|
284
|
-
) -> Literal[0, 1] | None: ...
|
|
285
|
-
@overload
|
|
286
|
-
def feedback(
|
|
287
|
-
self,
|
|
288
|
-
options: Literal["faces", "stars"] = ...,
|
|
289
|
-
*,
|
|
290
|
-
key: Key | None = None,
|
|
291
|
-
default: int | None = None,
|
|
292
|
-
disabled: bool = False,
|
|
293
|
-
on_change: WidgetCallback | None = None,
|
|
294
|
-
args: WidgetArgs | None = None,
|
|
295
|
-
kwargs: WidgetKwargs | None = None,
|
|
296
|
-
width: Width = "content",
|
|
297
|
-
) -> Literal[0, 1, 2, 3, 4] | None: ...
|
|
298
|
-
@gather_metrics("feedback")
|
|
299
|
-
def feedback(
|
|
300
|
-
self,
|
|
301
|
-
options: Literal["thumbs", "faces", "stars"] = "thumbs",
|
|
302
|
-
*,
|
|
303
|
-
key: Key | None = None,
|
|
304
|
-
default: int | None = None,
|
|
305
|
-
disabled: bool = False,
|
|
306
|
-
on_change: WidgetCallback | None = None,
|
|
307
|
-
args: WidgetArgs | None = None,
|
|
308
|
-
kwargs: WidgetKwargs | None = None,
|
|
309
|
-
width: Width = "content",
|
|
310
|
-
) -> int | None:
|
|
311
|
-
"""Display a feedback widget.
|
|
312
|
-
|
|
313
|
-
A feedback widget is an icon-based button group available in three
|
|
314
|
-
styles, as described in ``options``. It is commonly used in chat and AI
|
|
315
|
-
apps to allow users to rate responses.
|
|
316
|
-
|
|
317
|
-
Parameters
|
|
318
|
-
----------
|
|
319
|
-
options : "thumbs", "faces", or "stars"
|
|
320
|
-
The feedback options displayed to the user. ``options`` can be one
|
|
321
|
-
of the following:
|
|
322
|
-
|
|
323
|
-
- ``"thumbs"`` (default): Streamlit displays a thumb-up and
|
|
324
|
-
thumb-down button group.
|
|
325
|
-
- ``"faces"``: Streamlit displays a row of five buttons with
|
|
326
|
-
facial expressions depicting increasing satisfaction from left to
|
|
327
|
-
right.
|
|
328
|
-
- ``"stars"``: Streamlit displays a row of star icons, allowing the
|
|
329
|
-
user to select a rating from one to five stars.
|
|
330
|
-
|
|
331
|
-
key : str or int
|
|
332
|
-
An optional string or integer to use as the unique key for the widget.
|
|
333
|
-
If this is omitted, a key will be generated for the widget
|
|
334
|
-
based on its content. No two widgets may have the same key.
|
|
335
|
-
|
|
336
|
-
default : int or None
|
|
337
|
-
Default feedback value. This must be consistent with the feedback
|
|
338
|
-
type in ``options``:
|
|
339
|
-
|
|
340
|
-
- 0 or 1 if ``options="thumbs"``.
|
|
341
|
-
- Between 0 and 4, inclusive, if ``options="faces"`` or
|
|
342
|
-
``options="stars"``.
|
|
343
|
-
|
|
344
|
-
disabled : bool
|
|
345
|
-
An optional boolean that disables the feedback widget if set
|
|
346
|
-
to ``True``. The default is ``False``.
|
|
347
|
-
|
|
348
|
-
on_change : callable
|
|
349
|
-
An optional callback invoked when this feedback widget's value
|
|
350
|
-
changes.
|
|
351
|
-
|
|
352
|
-
args : list or tuple
|
|
353
|
-
An optional list or tuple of args to pass to the callback.
|
|
354
|
-
|
|
355
|
-
kwargs : dict
|
|
356
|
-
An optional dict of kwargs to pass to the callback.
|
|
357
|
-
|
|
358
|
-
width : "content", "stretch", or int
|
|
359
|
-
The width of the feedback widget. This can be one of the following:
|
|
360
|
-
|
|
361
|
-
- ``"content"`` (default): The width of the widget matches the
|
|
362
|
-
width of its content, but doesn't exceed the width of the parent
|
|
363
|
-
container.
|
|
364
|
-
- ``"stretch"``: The width of the widget matches the width of the
|
|
365
|
-
parent container.
|
|
366
|
-
- An integer specifying the width in pixels: The widget has a
|
|
367
|
-
fixed width. If the specified width is greater than the width of
|
|
368
|
-
the parent container, the width of the widget matches the width
|
|
369
|
-
of the parent container.
|
|
370
|
-
|
|
371
|
-
Returns
|
|
372
|
-
-------
|
|
373
|
-
int or None
|
|
374
|
-
An integer indicating the user's selection, where ``0`` is the
|
|
375
|
-
lowest feedback. Higher values indicate more positive feedback.
|
|
376
|
-
If no option was selected, the widget returns ``None``.
|
|
377
|
-
|
|
378
|
-
- For ``options="thumbs"``, a return value of ``0`` indicates
|
|
379
|
-
thumbs-down, and ``1`` indicates thumbs-up.
|
|
380
|
-
- For ``options="faces"`` and ``options="stars"``, return values
|
|
381
|
-
range from ``0`` (least satisfied) to ``4`` (most satisfied).
|
|
382
|
-
|
|
383
|
-
Examples
|
|
384
|
-
--------
|
|
385
|
-
Display a feedback widget with stars, and show the selected sentiment:
|
|
386
|
-
|
|
387
|
-
>>> import streamlit as st
|
|
388
|
-
>>>
|
|
389
|
-
>>> sentiment_mapping = ["one", "two", "three", "four", "five"]
|
|
390
|
-
>>> selected = st.feedback("stars")
|
|
391
|
-
>>> if selected is not None:
|
|
392
|
-
>>> st.markdown(f"You selected {sentiment_mapping[selected]} star(s).")
|
|
393
|
-
|
|
394
|
-
.. output::
|
|
395
|
-
https://doc-feedback-stars.streamlit.app/
|
|
396
|
-
height: 200px
|
|
397
|
-
|
|
398
|
-
Display a feedback widget with thumbs, and show the selected sentiment:
|
|
399
|
-
|
|
400
|
-
>>> import streamlit as st
|
|
401
|
-
>>>
|
|
402
|
-
>>> sentiment_mapping = [":material/thumb_down:", ":material/thumb_up:"]
|
|
403
|
-
>>> selected = st.feedback("thumbs")
|
|
404
|
-
>>> if selected is not None:
|
|
405
|
-
>>> st.markdown(f"You selected: {sentiment_mapping[selected]}")
|
|
406
|
-
|
|
407
|
-
.. output::
|
|
408
|
-
https://doc-feedback-thumbs.streamlit.app/
|
|
409
|
-
height: 200px
|
|
410
|
-
|
|
411
|
-
"""
|
|
412
|
-
|
|
413
|
-
if options not in {"thumbs", "faces", "stars"}:
|
|
414
|
-
raise StreamlitAPIException(
|
|
415
|
-
"The options argument to st.feedback must be one of "
|
|
416
|
-
"['thumbs', 'faces', 'stars']. "
|
|
417
|
-
f"The argument passed was '{options}'."
|
|
418
|
-
)
|
|
419
|
-
transformed_options, options_indices = get_mapped_options(options)
|
|
420
|
-
|
|
421
|
-
if default is not None and (default < 0 or default >= len(transformed_options)):
|
|
422
|
-
raise StreamlitAPIException(
|
|
423
|
-
f"The default value in '{options}' must be a number between 0 and {len(transformed_options) - 1}."
|
|
424
|
-
f" The passed default value is {default}"
|
|
425
|
-
)
|
|
426
|
-
|
|
427
|
-
# Convert small pixel widths to "content" to prevent icon wrapping.
|
|
428
|
-
# Calculate threshold based on theme.baseFontSize to be responsive to
|
|
429
|
-
# custom themes. The calculation is based on icon buttons sized in rem:
|
|
430
|
-
# - Button size: ~1.5rem (icon 1.25rem + padding 0.125rem x 2)
|
|
431
|
-
# - Gap: 0.125rem between buttons
|
|
432
|
-
# - thumbs: 2 buttons + 1 gap = 3.125rem
|
|
433
|
-
# - faces/stars: 5 buttons + 4 gaps = 8rem
|
|
434
|
-
base_font_size = config.get_option("theme.baseFontSize") or 16
|
|
435
|
-
button_size_rem = 1.5
|
|
436
|
-
gap_size_rem = 0.125
|
|
437
|
-
|
|
438
|
-
if options == "thumbs":
|
|
439
|
-
# 2 buttons + 1 gap
|
|
440
|
-
min_width_rem = 2 * button_size_rem + gap_size_rem
|
|
441
|
-
else:
|
|
442
|
-
# 5 buttons + 4 gaps (faces or stars)
|
|
443
|
-
min_width_rem = 5 * button_size_rem + 4 * gap_size_rem
|
|
444
|
-
|
|
445
|
-
# Convert rem to pixels based on base font size, add 10% buffer
|
|
446
|
-
min_width_threshold = int(min_width_rem * base_font_size * 1.1)
|
|
447
|
-
|
|
448
|
-
if isinstance(width, int) and width < min_width_threshold:
|
|
449
|
-
width = "content"
|
|
450
|
-
|
|
451
|
-
_default: list[int] | None = (
|
|
452
|
-
[options_indices[default]] if default is not None else None
|
|
453
|
-
)
|
|
454
|
-
serde = _SingleSelectSerde[int](options_indices, default_value=_default)
|
|
455
|
-
|
|
456
|
-
selection_visualization = ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
|
|
457
|
-
if options == "stars":
|
|
458
|
-
selection_visualization = (
|
|
459
|
-
ButtonGroupProto.SelectionVisualization.ALL_UP_TO_SELECTED
|
|
460
|
-
)
|
|
461
|
-
|
|
462
|
-
sentiment = self._button_group(
|
|
463
|
-
transformed_options,
|
|
464
|
-
default=_default,
|
|
465
|
-
key=key,
|
|
466
|
-
selection_mode="single",
|
|
467
|
-
disabled=disabled,
|
|
468
|
-
deserializer=serde.deserialize,
|
|
469
|
-
serializer=serde.serialize,
|
|
470
|
-
on_change=on_change,
|
|
471
|
-
args=args,
|
|
472
|
-
kwargs=kwargs,
|
|
473
|
-
selection_visualization=selection_visualization,
|
|
474
|
-
style="borderless",
|
|
475
|
-
width=width,
|
|
476
|
-
)
|
|
477
|
-
return sentiment.value
|
|
478
|
-
|
|
479
217
|
@overload
|
|
480
218
|
def pills(
|
|
481
219
|
self,
|
|
@@ -1023,18 +761,13 @@ class ButtonGroupMixin:
|
|
|
1023
761
|
default: list[int] | None = None,
|
|
1024
762
|
selection_mode: SelectionMode = "single",
|
|
1025
763
|
disabled: bool = False,
|
|
1026
|
-
style: Literal[
|
|
1027
|
-
"borderless", "pills", "segmented_control"
|
|
1028
|
-
] = "segmented_control",
|
|
764
|
+
style: Literal["pills", "segmented_control"] = "segmented_control",
|
|
1029
765
|
format_func: Callable[[V], ButtonGroupProto.Option] | None = None,
|
|
1030
766
|
deserializer: WidgetDeserializer[T],
|
|
1031
767
|
serializer: WidgetSerializer[T],
|
|
1032
768
|
on_change: WidgetCallback | None = None,
|
|
1033
769
|
args: WidgetArgs | None = None,
|
|
1034
770
|
kwargs: WidgetKwargs | None = None,
|
|
1035
|
-
selection_visualization: ButtonGroupProto.SelectionVisualization.ValueType = (
|
|
1036
|
-
ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
|
|
1037
|
-
),
|
|
1038
771
|
label: str | None = None,
|
|
1039
772
|
label_visibility: LabelVisibility = "visible",
|
|
1040
773
|
help: str | None = None,
|
|
@@ -1062,9 +795,9 @@ class ButtonGroupMixin:
|
|
|
1062
795
|
"`selection_mode='single'`."
|
|
1063
796
|
)
|
|
1064
797
|
|
|
1065
|
-
if style not in {"
|
|
798
|
+
if style not in {"pills", "segmented_control"}:
|
|
1066
799
|
raise StreamlitAPIException(
|
|
1067
|
-
"The style argument must be one of ['
|
|
800
|
+
"The style argument must be one of ['pills', 'segmented_control']. "
|
|
1068
801
|
f"The argument passed was '{style}'."
|
|
1069
802
|
)
|
|
1070
803
|
|
|
@@ -1091,11 +824,9 @@ class ButtonGroupMixin:
|
|
|
1091
824
|
)
|
|
1092
825
|
|
|
1093
826
|
element_id = compute_and_register_element_id(
|
|
1094
|
-
|
|
1095
|
-
# "feedback" in errors
|
|
1096
|
-
"feedback" if style == "borderless" else style,
|
|
827
|
+
style,
|
|
1097
828
|
user_key=key,
|
|
1098
|
-
# Treat the provided key as the main identity for segmented_control
|
|
829
|
+
# Treat the provided key as the main identity for segmented_control and pills,
|
|
1099
830
|
# and only include kwargs that can invalidate the current selection.
|
|
1100
831
|
# We whitelist the formatted options and the click mode (single vs multi).
|
|
1101
832
|
key_as_main_identity={"options", "click_mode"},
|
|
@@ -1116,7 +847,6 @@ class ButtonGroupMixin:
|
|
|
1116
847
|
disabled,
|
|
1117
848
|
form_id,
|
|
1118
849
|
click_mode=parsed_selection_mode,
|
|
1119
|
-
selection_visualization=selection_visualization,
|
|
1120
850
|
style=style,
|
|
1121
851
|
label=label,
|
|
1122
852
|
label_visibility=label_visibility,
|