streamlit-nightly 1.53.2.dev20260202__py3-none-any.whl → 1.54.1.dev20260204__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/logo.py +6 -10
- streamlit/components/v2/component_path_utils.py +17 -29
- streamlit/config.py +4 -2
- streamlit/elements/arrow.py +66 -26
- streamlit/elements/lib/built_in_chart_utils.py +1 -1
- streamlit/elements/lib/column_config_utils.py +4 -4
- streamlit/elements/lib/options_selector_utils.py +4 -0
- streamlit/elements/lib/pandas_styler_utils.py +22 -22
- streamlit/elements/widgets/button_group.py +221 -86
- streamlit/elements/widgets/data_editor.py +9 -9
- streamlit/elements/widgets/radio.py +8 -4
- streamlit/hello/dataframe_demo.py +1 -1
- streamlit/path_security.py +98 -0
- streamlit/proto/ArrowData_pb2.py +5 -3
- streamlit/proto/ArrowData_pb2.pyi +44 -4
- streamlit/proto/ArrowNamedDataSet_pb2.py +4 -4
- streamlit/proto/ArrowNamedDataSet_pb2.pyi +3 -3
- streamlit/proto/ArrowVegaLiteChart_pb2.py +4 -4
- streamlit/proto/ArrowVegaLiteChart_pb2.pyi +3 -3
- streamlit/proto/ButtonGroup_pb2.py +8 -8
- streamlit/proto/ButtonGroup_pb2.pyi +9 -7
- streamlit/proto/Dataframe_pb2.py +31 -0
- streamlit/proto/{Arrow_pb2.pyi → Dataframe_pb2.pyi} +39 -102
- streamlit/proto/Element_pb2.py +5 -4
- streamlit/proto/Element_pb2.pyi +11 -10
- streamlit/proto/Table_pb2.py +29 -0
- streamlit/proto/Table_pb2.pyi +83 -0
- streamlit/runtime/app_session.py +9 -1
- streamlit/static/index.html +1 -1
- streamlit/static/manifest.json +307 -307
- streamlit/static/static/js/{ErrorOutline.esm.CLuz0rSD.js → ErrorOutline.esm.DWBqsdHn.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.CO68LcnZ.js → FileDownload.esm.D5koxJhf.js} +1 -1
- streamlit/static/static/js/{FileHelper.DAXgY6Ug.js → FileHelper.kJKftfu4.js} +5 -5
- streamlit/static/static/js/{FormClearHelper.zxJ53Nym.js → FormClearHelper.CyGGPn10.js} +1 -1
- streamlit/static/static/js/{InputInstructions.CCbg8esE.js → InputInstructions.oezYb8Lm.js} +1 -1
- streamlit/static/static/js/{Particles.BJw0A-zv.js → Particles.BIpBmEwi.js} +1 -1
- streamlit/static/static/js/{ProgressBar.BrrHeAEh.js → ProgressBar.BRAS_FJc.js} +1 -1
- streamlit/static/static/js/{StreamlitSyntaxHighlighter.DvPLy3zk.js → StreamlitSyntaxHighlighter.c2qcx-xG.js} +2 -2
- streamlit/static/static/js/{TableChart.esm.BawvAi5p.js → TableChart.esm.BuemQLVW.js} +1 -1
- streamlit/static/static/js/{Toolbar.CbpscbNb.js → Toolbar.mUe2Nmta.js} +1 -1
- streamlit/static/static/js/{WidgetLabelHelpIconInline.DA4S2HFP.js → WidgetLabelHelpIconInline.if89y2mu.js} +1 -1
- streamlit/static/static/js/{base-input.BKKl2eBF.js → base-input.AJ4KxBTh.js} +4 -4
- streamlit/static/static/js/{checkbox.CB43AKV4.js → checkbox.GY4JoJkM.js} +1 -1
- streamlit/static/static/js/{createDownloadLinkElement.jVwF96ey.js → createDownloadLinkElement.BWJh90jh.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.CxQizSv7.js → data-grid-overlay-editor.C9AINtRf.js} +1 -1
- streamlit/static/static/js/{downloader.CKlIgsy5.js → downloader.BZY8OE4f.js} +1 -1
- streamlit/static/static/js/{embed.BhRb_2n8.js → embed.BjO7Ez0y.js} +1 -1
- streamlit/static/static/js/{es6.DPyfPmWm.js → es6.eb5oR8iN.js} +2 -2
- streamlit/static/static/js/{formatNumber.DtfMnnPx.js → formatNumber.CCeQsvJQ.js} +1 -1
- streamlit/static/static/js/{iconPosition.DkZAlu_k.js → iconPosition.D6eEnKvO.js} +1 -1
- streamlit/static/static/js/{iframeResizer.contentWindow.l5sQWLra.js → iframeResizer.contentWindow.DTsWJRTo.js} +1 -1
- streamlit/static/static/js/{index.rvbQETlC.js → index.B6l4FdUv.js} +1 -1
- streamlit/static/static/js/{index.BUlT_mOL.js → index.B7H2q9vo.js} +2 -2
- streamlit/static/static/js/{index.CsIENsKH.js → index.BDdmrM58.js} +1 -1
- streamlit/static/static/js/{index.e6Ry6-Ft.js → index.BMbQnwRD.js} +1 -1
- streamlit/static/static/js/{index.CL_icBXS.js → index.BQ5MOzHu.js} +1 -1
- streamlit/static/static/js/{index.Ccye_uLl.js → index.BSgo_bkv.js} +1 -1
- streamlit/static/static/js/{index.LjqoQCm5.js → index.BU5M9DsN.js} +1 -1
- streamlit/static/static/js/{index.Bc_FQ4Wb.js → index.BYIxnU34.js} +1 -1
- streamlit/static/static/js/{index.y0h42OXL.js → index.BZL2hIBz.js} +1 -1
- streamlit/static/static/js/{index.Dac9Jib-.js → index.BZVrJlnq.js} +1 -1
- streamlit/static/static/js/{index.BLD3tJ2C.js → index.Bd7QK46M.js} +1 -1
- streamlit/static/static/js/{index.Ck64OQhV.js → index.BfHA_i34.js} +1 -1
- streamlit/static/static/js/{index.BpCj2-sQ.js → index.Bgry-Ek_.js} +1 -1
- streamlit/static/static/js/{index.D83azq2w.js → index.Bi25zaXA.js} +1 -1
- streamlit/static/static/js/{index.Cwg8nWw5.js → index.Bj3M1xBC.js} +1 -1
- streamlit/static/static/js/{index.DmWUXdjc.js → index.Bjrvlqx5.js} +16 -16
- streamlit/static/static/js/index.BnOSeM5K.js +11 -0
- streamlit/static/static/js/index.BoL6J1jK.js +2 -0
- streamlit/static/static/js/{index.yHLCvUGh.js → index.BoORyxOa.js} +1 -1
- streamlit/static/static/js/{index.DiBeetOH.js → index.Bpd7GPeH.js} +1 -1
- streamlit/static/static/js/{index.BzO83wKm.js → index.BpeJX018.js} +1 -1
- streamlit/static/static/js/{index.C_19KWNs.js → index.BriH7JVk.js} +1 -1
- streamlit/static/static/js/{index.DjuMEZ6m.js → index.BwkeObMo.js} +1 -1
- streamlit/static/static/js/{index.CiS4giQ2.js → index.C0o85qmd.js} +1 -1
- streamlit/static/static/js/{index.L9pOjBEn.js → index.C7_wNJTH.js} +2 -2
- streamlit/static/static/js/{index.DzdPUxsx.js → index.CGZP_w9b.js} +1 -1
- streamlit/static/static/js/{index.DKoJr0Se.js → index.CGw52-0-.js} +1 -1
- streamlit/static/static/js/{index.6J1N4is3.js → index.CUvtJj0a.js} +1 -1
- streamlit/static/static/js/{index.CBbYMKZp.js → index.Cfx1ZHWt.js} +1 -1
- streamlit/static/static/js/{index.BAK0CG1Q.js → index.Chl2kALe.js} +1 -1
- streamlit/static/static/js/index.Crlx_wdE.js +1 -0
- streamlit/static/static/js/{index.WIMtx3m0.js → index.D9A-8ebQ.js} +1 -1
- streamlit/static/static/js/{index.y5HxPwg9.js → index.DBIoNOen.js} +21 -21
- streamlit/static/static/js/{index.AZ9T4EqJ.js → index.DMKTAe4F.js} +1 -1
- streamlit/static/static/js/{index.YutgmD9x.js → index.DNrpqKVt.js} +2 -2
- streamlit/static/static/js/{index.Y9wPTZIf.js → index.DSRvF_8e.js} +1 -1
- streamlit/static/static/js/{index.DZOGT9vX.js → index.DhB1m_xG.js} +1 -1
- streamlit/static/static/js/{index.DR6V0uBJ.js → index.DiES30vM.js} +1 -1
- streamlit/static/static/js/{index.CmbqbRMZ.js → index.DlJ4Y1xc.js} +1 -1
- streamlit/static/static/js/{index.FioS1Y9m.js → index.J61yByUR.js} +1 -1
- streamlit/static/static/js/{index.hnu9U-5g.js → index.JxDTXE8N.js} +1 -1
- streamlit/static/static/js/{index.CaU3Uv_L.js → index.KGr28TP8.js} +1 -1
- streamlit/static/static/js/{index.465nmxtO.js → index.Pgm3rRpH.js} +1 -1
- streamlit/static/static/js/{index.DpSc4e1j.js → index.XzcYOc9I.js} +1 -1
- streamlit/static/static/js/{index.OizPL4jg.js → index.Z_u7ZS4h.js} +1 -1
- streamlit/static/static/js/{index.CL7it7tU.js → index.hDg7x0Tp.js} +1 -1
- streamlit/static/static/js/{index.b_f-McZ5.js → index.k7p0hmaU.js} +1 -1
- streamlit/static/static/js/{index.CsEZTo6L.js → index.syoxWolF.js} +1 -1
- streamlit/static/static/js/{index.Q2t_iBn0.js → index.xZ651bTg.js} +1 -1
- streamlit/static/static/js/{input.CAtwSQ27.js → input.C-PwAMG6.js} +1 -1
- streamlit/static/static/js/{main.VeMVx6VI.js → main.fMmyxXOf.js} +1 -1
- streamlit/static/static/js/{memory.CxS_lIUn.js → memory.BG__eDEj.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.CoqRgZW_.js → number-overlay-editor.C0n-91sR.js} +1 -1
- streamlit/static/static/js/{pandasStylerUtils.DGWgd5sM.js → pandasStylerUtils.BqWaUzvh.js} +1 -1
- streamlit/static/static/js/{sandbox.2mSqEau0.js → sandbox.CHhc-txg.js} +1 -1
- streamlit/static/static/js/{sprintfjs.CsoVVZ9k.js → sprintfjs.BlFBKfMf.js} +1 -1
- streamlit/static/static/js/{styled-components.BShfh7J8.js → styled-components.D5uOQqN2.js} +1 -1
- streamlit/static/static/js/{throttle.Fq1DQK4p.js → throttle.DlZC3xNA.js} +1 -1
- streamlit/static/static/js/{timepicker.DmyY-qtn.js → timepicker._TfRUaDL.js} +4 -4
- streamlit/static/static/js/{toConsumableArray.Dvd9AIqV.js → toConsumableArray.CZW4AmuW.js} +2 -2
- streamlit/static/static/js/uniqueId.CTTDAAaF.js +1 -0
- streamlit/static/static/js/useBasicWidgetState.Bx27912z.js +1 -0
- streamlit/static/static/js/{useIntlLocale.kdIj0ego.js → useIntlLocale.DsOvysl7.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.DkuG1C1S.js → useTextInputAutoExpand.C9g8px1W.js} +1 -1
- streamlit/static/static/js/{useUpdateUiValue.-UI_JsjT.js → useUpdateUiValue.fF-Cntkp.js} +1 -1
- streamlit/static/static/js/{useWaveformController.C5PTwL6I.js → useWaveformController.C5EtFoJE.js} +1 -1
- streamlit/static/static/js/{withCalculatedWidth.BREyS0pJ.js → withCalculatedWidth.CcvaXQb0.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.DYDiEOrW.js → withFullScreenWrapper.DP61hzLF.js} +1 -1
- streamlit/testing/v1/element_tree.py +20 -15
- 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/routes.py +14 -0
- streamlit/web/server/server.py +4 -0
- 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.dev20260202.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/RECORD +135 -131
- streamlit/proto/Arrow_pb2.py +0 -34
- streamlit/static/static/js/index.CAoX2tlo.js +0 -2
- streamlit/static/static/js/index.DDr-BLbJ.js +0 -1
- streamlit/static/static/js/index.DL_ywOgf.js +0 -11
- streamlit/static/static/js/uniqueId.CCajdEK8.js +0 -1
- streamlit/static/static/js/useBasicWidgetState.COLQ5AFB.js +0 -1
- {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/top_level.txt +0 -0
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/elements/arrow.py
CHANGED
|
@@ -52,8 +52,9 @@ from streamlit.elements.lib.pandas_styler_utils import marshall_styler
|
|
|
52
52
|
from streamlit.elements.lib.policies import check_widget_policies
|
|
53
53
|
from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
|
|
54
54
|
from streamlit.errors import StreamlitAPIException, StreamlitValueError
|
|
55
|
-
from streamlit.proto.
|
|
55
|
+
from streamlit.proto.Dataframe_pb2 import Dataframe as DataframeProto
|
|
56
56
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
|
57
|
+
from streamlit.proto.Table_pb2 import Table as TableProto
|
|
57
58
|
from streamlit.runtime.metrics_util import gather_metrics
|
|
58
59
|
from streamlit.runtime.scriptrunner_utils.script_run_context import (
|
|
59
60
|
enqueue_message,
|
|
@@ -71,6 +72,7 @@ if TYPE_CHECKING:
|
|
|
71
72
|
from streamlit.dataframe_util import Data
|
|
72
73
|
from streamlit.delta_generator import DeltaGenerator
|
|
73
74
|
from streamlit.elements.lib.built_in_chart_utils import AddRowsMetadata
|
|
75
|
+
from streamlit.proto.ArrowData_pb2 import ArrowData as ArrowDataProto
|
|
74
76
|
|
|
75
77
|
|
|
76
78
|
SelectionMode: TypeAlias = Literal[
|
|
@@ -223,7 +225,7 @@ class DataframeSelectionSerde:
|
|
|
223
225
|
|
|
224
226
|
def parse_selection_mode(
|
|
225
227
|
selection_mode: SelectionMode | Iterable[SelectionMode],
|
|
226
|
-
) -> set[
|
|
228
|
+
) -> set[DataframeProto.SelectionMode.ValueType]:
|
|
227
229
|
"""Parse and check the user provided selection modes."""
|
|
228
230
|
if isinstance(selection_mode, str):
|
|
229
231
|
# Only a single selection mode was passed
|
|
@@ -256,28 +258,28 @@ def parse_selection_mode(
|
|
|
256
258
|
parsed_selection_modes = []
|
|
257
259
|
for mode in selection_mode_set:
|
|
258
260
|
if mode == "single-row":
|
|
259
|
-
parsed_selection_modes.append(
|
|
261
|
+
parsed_selection_modes.append(DataframeProto.SelectionMode.SINGLE_ROW)
|
|
260
262
|
elif mode == "multi-row":
|
|
261
|
-
parsed_selection_modes.append(
|
|
263
|
+
parsed_selection_modes.append(DataframeProto.SelectionMode.MULTI_ROW)
|
|
262
264
|
elif mode == "single-column":
|
|
263
|
-
parsed_selection_modes.append(
|
|
265
|
+
parsed_selection_modes.append(DataframeProto.SelectionMode.SINGLE_COLUMN)
|
|
264
266
|
elif mode == "multi-column":
|
|
265
|
-
parsed_selection_modes.append(
|
|
267
|
+
parsed_selection_modes.append(DataframeProto.SelectionMode.MULTI_COLUMN)
|
|
266
268
|
elif mode == "single-cell":
|
|
267
|
-
parsed_selection_modes.append(
|
|
269
|
+
parsed_selection_modes.append(DataframeProto.SelectionMode.SINGLE_CELL)
|
|
268
270
|
elif mode == "multi-cell":
|
|
269
|
-
parsed_selection_modes.append(
|
|
271
|
+
parsed_selection_modes.append(DataframeProto.SelectionMode.MULTI_CELL)
|
|
270
272
|
return set(parsed_selection_modes)
|
|
271
273
|
|
|
272
274
|
|
|
273
275
|
def parse_border_mode(
|
|
274
276
|
border: bool | Literal["horizontal"],
|
|
275
|
-
) ->
|
|
277
|
+
) -> TableProto.BorderMode.ValueType:
|
|
276
278
|
"""Parse and check the user provided border mode."""
|
|
277
279
|
if isinstance(border, bool):
|
|
278
|
-
return
|
|
280
|
+
return TableProto.BorderMode.ALL if border else TableProto.BorderMode.NONE
|
|
279
281
|
if border == "horizontal":
|
|
280
|
-
return
|
|
282
|
+
return TableProto.BorderMode.HORIZONTAL
|
|
281
283
|
raise StreamlitValueError("border", ["True", "False", "'horizontal'"])
|
|
282
284
|
|
|
283
285
|
|
|
@@ -695,7 +697,7 @@ class ArrowMixin:
|
|
|
695
697
|
# Convert the user provided column config into the frontend compatible format:
|
|
696
698
|
column_config_mapping = process_config_mapping(column_config)
|
|
697
699
|
|
|
698
|
-
proto =
|
|
700
|
+
proto = DataframeProto()
|
|
699
701
|
|
|
700
702
|
if row_height:
|
|
701
703
|
proto.row_height = row_height
|
|
@@ -706,12 +708,14 @@ class ArrowMixin:
|
|
|
706
708
|
if placeholder is not None:
|
|
707
709
|
proto.placeholder = placeholder
|
|
708
710
|
|
|
709
|
-
proto.editing_mode =
|
|
711
|
+
proto.editing_mode = DataframeProto.EditingMode.READ_ONLY
|
|
710
712
|
|
|
711
713
|
has_range_index: bool = False
|
|
712
714
|
if isinstance(data, pa.Table):
|
|
713
715
|
# For pyarrow tables, we can just serialize the table directly
|
|
714
|
-
proto.data = dataframe_util.convert_arrow_table_to_arrow_bytes(
|
|
716
|
+
proto.arrow_data.data = dataframe_util.convert_arrow_table_to_arrow_bytes(
|
|
717
|
+
data
|
|
718
|
+
)
|
|
715
719
|
else:
|
|
716
720
|
# For all other data formats, we need to convert them to a pandas.DataFrame
|
|
717
721
|
# thereby, we also apply some data specific configs
|
|
@@ -725,7 +729,7 @@ class ArrowMixin:
|
|
|
725
729
|
# when the position of the element is changed.
|
|
726
730
|
delta_path = self.dg._get_delta_path_str()
|
|
727
731
|
default_uuid = str(hash(delta_path))
|
|
728
|
-
marshall_styler(proto, data, default_uuid)
|
|
732
|
+
marshall_styler(proto.arrow_data, data, default_uuid)
|
|
729
733
|
|
|
730
734
|
# Convert the input data into a pandas.DataFrame
|
|
731
735
|
data_df = dataframe_util.convert_anything_to_pandas_df(
|
|
@@ -734,7 +738,9 @@ class ArrowMixin:
|
|
|
734
738
|
has_range_index = dataframe_util.has_range_index(data_df)
|
|
735
739
|
apply_data_specific_configs(column_config_mapping, data_format)
|
|
736
740
|
# Serialize the data to bytes:
|
|
737
|
-
proto.data = dataframe_util.convert_pandas_df_to_arrow_bytes(
|
|
741
|
+
proto.arrow_data.data = dataframe_util.convert_pandas_df_to_arrow_bytes(
|
|
742
|
+
data_df
|
|
743
|
+
)
|
|
738
744
|
|
|
739
745
|
if hide_index is not None:
|
|
740
746
|
update_column_config(
|
|
@@ -782,7 +788,7 @@ class ArrowMixin:
|
|
|
782
788
|
# selection state in this case.
|
|
783
789
|
key_as_main_identity={"selection_mode", "is_selection_activated"},
|
|
784
790
|
dg=self.dg,
|
|
785
|
-
data=proto.data,
|
|
791
|
+
data=proto.arrow_data.data,
|
|
786
792
|
width=width,
|
|
787
793
|
height=height,
|
|
788
794
|
use_container_width=use_container_width,
|
|
@@ -803,9 +809,9 @@ class ArrowMixin:
|
|
|
803
809
|
ctx=ctx,
|
|
804
810
|
value_type="string_value",
|
|
805
811
|
)
|
|
806
|
-
self.dg._enqueue("
|
|
812
|
+
self.dg._enqueue("dataframe", proto, layout_config=layout_config)
|
|
807
813
|
return widget_state.value
|
|
808
|
-
return self.dg._enqueue("
|
|
814
|
+
return self.dg._enqueue("dataframe", proto, layout_config=layout_config)
|
|
809
815
|
|
|
810
816
|
@gather_metrics("table")
|
|
811
817
|
def table(
|
|
@@ -911,10 +917,10 @@ class ArrowMixin:
|
|
|
911
917
|
height="content",
|
|
912
918
|
)
|
|
913
919
|
|
|
914
|
-
proto =
|
|
915
|
-
|
|
920
|
+
proto = TableProto()
|
|
921
|
+
marshall_table(proto.arrow_data, data, default_uuid)
|
|
916
922
|
proto.border_mode = border_mode
|
|
917
|
-
return self.dg._enqueue("
|
|
923
|
+
return self.dg._enqueue("table", proto, layout_config=layout_config)
|
|
918
924
|
|
|
919
925
|
@gather_metrics("add_rows")
|
|
920
926
|
def add_rows(self, data: Data = None, **kwargs: Any) -> DeltaGenerator | None:
|
|
@@ -1148,13 +1154,15 @@ def _arrow_add_rows(
|
|
|
1148
1154
|
return dg
|
|
1149
1155
|
|
|
1150
1156
|
|
|
1151
|
-
def marshall(
|
|
1152
|
-
|
|
1157
|
+
def marshall(
|
|
1158
|
+
proto: ArrowDataProto, data: Data, default_uuid: str | None = None
|
|
1159
|
+
) -> None:
|
|
1160
|
+
"""Marshall pandas.DataFrame into an ArrowData proto.
|
|
1153
1161
|
|
|
1154
1162
|
Parameters
|
|
1155
1163
|
----------
|
|
1156
|
-
proto : proto.
|
|
1157
|
-
Output. The protobuf for Streamlit
|
|
1164
|
+
proto : proto.ArrowData
|
|
1165
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
1158
1166
|
|
|
1159
1167
|
data : pandas.DataFrame, pandas.Styler, pyarrow.Table, numpy.ndarray, pyspark.sql.DataFrame, snowflake.snowpark.DataFrame, Iterable, dict, or None
|
|
1160
1168
|
Something that is or can be converted to a dataframe.
|
|
@@ -1176,3 +1184,35 @@ def marshall(proto: ArrowProto, data: Data, default_uuid: str | None = None) ->
|
|
|
1176
1184
|
marshall_styler(proto, data, default_uuid)
|
|
1177
1185
|
|
|
1178
1186
|
proto.data = dataframe_util.convert_anything_to_arrow_bytes(data)
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
def marshall_table(
|
|
1190
|
+
proto: ArrowDataProto, data: Data, default_uuid: str | None = None
|
|
1191
|
+
) -> None:
|
|
1192
|
+
"""Marshall data into an ArrowData proto for Table element.
|
|
1193
|
+
|
|
1194
|
+
Parameters
|
|
1195
|
+
----------
|
|
1196
|
+
proto : proto.ArrowData
|
|
1197
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
1198
|
+
|
|
1199
|
+
data : pandas.DataFrame, pandas.Styler, pyarrow.Table, numpy.ndarray, pyspark.sql.DataFrame, snowflake.snowpark.DataFrame, Iterable, dict, or None
|
|
1200
|
+
Something that is or can be converted to a dataframe.
|
|
1201
|
+
|
|
1202
|
+
default_uuid : str | None
|
|
1203
|
+
If pandas.Styler UUID is not provided, this value will be used.
|
|
1204
|
+
This attribute is optional and only used for pandas.Styler, other elements
|
|
1205
|
+
can ignore it.
|
|
1206
|
+
|
|
1207
|
+
""" # noqa: E501
|
|
1208
|
+
|
|
1209
|
+
if dataframe_util.is_pandas_styler(data):
|
|
1210
|
+
# default_uuid is a string only if the data is a `Styler`,
|
|
1211
|
+
# and `None` otherwise.
|
|
1212
|
+
if not isinstance(default_uuid, str):
|
|
1213
|
+
raise StreamlitAPIException(
|
|
1214
|
+
"Default UUID must be a string for Styler data."
|
|
1215
|
+
)
|
|
1216
|
+
marshall_styler(proto, data, default_uuid)
|
|
1217
|
+
|
|
1218
|
+
proto.data = dataframe_util.convert_anything_to_arrow_bytes(data)
|
|
@@ -671,7 +671,7 @@ def _drop_unused_columns(df: pd.DataFrame, *column_names: str | None) -> pd.Data
|
|
|
671
671
|
seen.add(x)
|
|
672
672
|
keep.append(x)
|
|
673
673
|
|
|
674
|
-
return df[keep]
|
|
674
|
+
return df[keep] # type: ignore[no-any-return, unused-ignore]
|
|
675
675
|
|
|
676
676
|
|
|
677
677
|
def _maybe_convert_color_column_in_place(
|
|
@@ -29,7 +29,7 @@ if TYPE_CHECKING:
|
|
|
29
29
|
import pyarrow as pa
|
|
30
30
|
from pandas import DataFrame, Index, Series
|
|
31
31
|
|
|
32
|
-
from streamlit.proto.
|
|
32
|
+
from streamlit.proto.Dataframe_pb2 import Dataframe as DataframeProto
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
# The index identifier can be used to apply configuration options
|
|
@@ -539,13 +539,13 @@ def _convert_column_config_to_json(column_config_mapping: ColumnConfigMapping) -
|
|
|
539
539
|
|
|
540
540
|
|
|
541
541
|
def marshall_column_config(
|
|
542
|
-
proto:
|
|
542
|
+
proto: DataframeProto, column_config_mapping: ColumnConfigMapping
|
|
543
543
|
) -> None:
|
|
544
|
-
"""Marshall the column config into the
|
|
544
|
+
"""Marshall the column config into the Dataframe proto.
|
|
545
545
|
|
|
546
546
|
Parameters
|
|
547
547
|
----------
|
|
548
|
-
proto :
|
|
548
|
+
proto : DataframeProto
|
|
549
549
|
The proto to marshall into.
|
|
550
550
|
|
|
551
551
|
column_config_mapping : ColumnConfigMapping
|
|
@@ -277,6 +277,10 @@ def create_mappings(
|
|
|
277
277
|
for index, option in enumerate(options):
|
|
278
278
|
formatted_option = format_func(option)
|
|
279
279
|
formatted_options.append(formatted_option)
|
|
280
|
+
# If formatted labels are duplicated, the last one wins. We keep this
|
|
281
|
+
# behavior to mirror radio/selectbox/multiselect, but it makes selection
|
|
282
|
+
# ambiguous for string-based widgets.
|
|
283
|
+
# TODO: Consider raising a StreamlitAPIException on duplicate labels.
|
|
280
284
|
formatted_option_to_option_mapping[formatted_option] = index
|
|
281
285
|
|
|
282
286
|
return (
|
|
@@ -25,18 +25,18 @@ if TYPE_CHECKING:
|
|
|
25
25
|
from pandas import DataFrame
|
|
26
26
|
from pandas.io.formats.style import Styler
|
|
27
27
|
|
|
28
|
-
from streamlit.proto.
|
|
28
|
+
from streamlit.proto.ArrowData_pb2 import ArrowData as ArrowDataProto
|
|
29
29
|
|
|
30
30
|
from enum import Enum
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def marshall_styler(proto:
|
|
34
|
-
"""Marshall pandas.Styler into an
|
|
33
|
+
def marshall_styler(proto: ArrowDataProto, styler: Styler, default_uuid: str) -> None:
|
|
34
|
+
"""Marshall pandas.Styler into an ArrowData proto.
|
|
35
35
|
|
|
36
36
|
Parameters
|
|
37
37
|
----------
|
|
38
|
-
proto : proto.
|
|
39
|
-
Output. The protobuf for Streamlit
|
|
38
|
+
proto : proto.ArrowData
|
|
39
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
40
40
|
|
|
41
41
|
styler : pandas.Styler
|
|
42
42
|
Helps style a DataFrame or Series according to the data with HTML and CSS.
|
|
@@ -71,13 +71,13 @@ def marshall_styler(proto: ArrowProto, styler: Styler, default_uuid: str) -> Non
|
|
|
71
71
|
_marshall_display_values(proto, styler_data_df, pandas_styles)
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
def _marshall_uuid(proto:
|
|
75
|
-
"""Marshall pandas.Styler uuid into an
|
|
74
|
+
def _marshall_uuid(proto: ArrowDataProto, styler: Styler, default_uuid: str) -> None:
|
|
75
|
+
"""Marshall pandas.Styler uuid into an ArrowData proto.
|
|
76
76
|
|
|
77
77
|
Parameters
|
|
78
78
|
----------
|
|
79
|
-
proto : proto.
|
|
80
|
-
Output. The protobuf for Streamlit
|
|
79
|
+
proto : proto.ArrowData
|
|
80
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
81
81
|
|
|
82
82
|
styler : pandas.Styler
|
|
83
83
|
Helps style a DataFrame or Series according to the data with HTML and CSS.
|
|
@@ -92,13 +92,13 @@ def _marshall_uuid(proto: ArrowProto, styler: Styler, default_uuid: str) -> None
|
|
|
92
92
|
proto.styler.uuid = str(styler.uuid) # type: ignore[attr-defined]
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
def _marshall_caption(proto:
|
|
96
|
-
"""Marshall pandas.Styler caption into an
|
|
95
|
+
def _marshall_caption(proto: ArrowDataProto, styler: Styler) -> None:
|
|
96
|
+
"""Marshall pandas.Styler caption into an ArrowData proto.
|
|
97
97
|
|
|
98
98
|
Parameters
|
|
99
99
|
----------
|
|
100
|
-
proto : proto.
|
|
101
|
-
Output. The protobuf for Streamlit
|
|
100
|
+
proto : proto.ArrowData
|
|
101
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
102
102
|
|
|
103
103
|
styler : pandas.Styler
|
|
104
104
|
Helps style a DataFrame or Series according to the data with HTML and CSS.
|
|
@@ -109,14 +109,14 @@ def _marshall_caption(proto: ArrowProto, styler: Styler) -> None:
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
def _marshall_styles(
|
|
112
|
-
proto:
|
|
112
|
+
proto: ArrowDataProto, styler: Styler, styles: Mapping[str, Any]
|
|
113
113
|
) -> None:
|
|
114
|
-
"""Marshall pandas.Styler styles into an
|
|
114
|
+
"""Marshall pandas.Styler styles into an ArrowData proto.
|
|
115
115
|
|
|
116
116
|
Parameters
|
|
117
117
|
----------
|
|
118
|
-
proto : proto.
|
|
119
|
-
Output. The protobuf for Streamlit
|
|
118
|
+
proto : proto.ArrowData
|
|
119
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
120
120
|
|
|
121
121
|
styler : pandas.Styler
|
|
122
122
|
Helps style a DataFrame or Series according to the data with HTML and CSS.
|
|
@@ -228,14 +228,14 @@ def _pandas_style_to_css(
|
|
|
228
228
|
|
|
229
229
|
|
|
230
230
|
def _marshall_display_values(
|
|
231
|
-
proto:
|
|
231
|
+
proto: ArrowDataProto, df: DataFrame, styles: Mapping[str, Any]
|
|
232
232
|
) -> None:
|
|
233
|
-
"""Marshall pandas.Styler display values into an
|
|
233
|
+
"""Marshall pandas.Styler display values into an ArrowData proto.
|
|
234
234
|
|
|
235
235
|
Parameters
|
|
236
236
|
----------
|
|
237
|
-
proto : proto.
|
|
238
|
-
Output. The protobuf for Streamlit
|
|
237
|
+
proto : proto.ArrowData
|
|
238
|
+
Output. The protobuf for Streamlit ArrowData proto.
|
|
239
239
|
|
|
240
240
|
df : pandas.DataFrame
|
|
241
241
|
A dataframe with original values.
|
|
@@ -299,4 +299,4 @@ def _use_display_values(df: DataFrame, styles: Mapping[str, Any]) -> DataFrame:
|
|
|
299
299
|
# Batch-assign updates for this column using iloc for performance.
|
|
300
300
|
new_df.iloc[row_indices, col_idx] = values
|
|
301
301
|
|
|
302
|
-
return new_df
|
|
302
|
+
return new_df # type: ignore[no-any-return, unused-ignore]
|