streamlit-nightly 1.53.2.dev20260203__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/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/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/static/index.html +1 -1
- streamlit/static/manifest.json +308 -308
- streamlit/static/static/js/{ErrorOutline.esm.C9uHPmIj.js → ErrorOutline.esm.DWBqsdHn.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.D-YPxF3t.js → FileDownload.esm.D5koxJhf.js} +1 -1
- streamlit/static/static/js/{FileHelper.DQSH0zYW.js → FileHelper.kJKftfu4.js} +5 -5
- streamlit/static/static/js/{FormClearHelper.DQoXcOWo.js → FormClearHelper.CyGGPn10.js} +1 -1
- streamlit/static/static/js/{InputInstructions.C7VMyGT7.js → InputInstructions.oezYb8Lm.js} +1 -1
- streamlit/static/static/js/{Particles.BdQSRZde.js → Particles.BIpBmEwi.js} +1 -1
- streamlit/static/static/js/{ProgressBar.DNF_pWKr.js → ProgressBar.BRAS_FJc.js} +1 -1
- streamlit/static/static/js/{StreamlitSyntaxHighlighter.Cys9Bt18.js → StreamlitSyntaxHighlighter.c2qcx-xG.js} +1 -1
- streamlit/static/static/js/{TableChart.esm.B9SMgSK4.js → TableChart.esm.BuemQLVW.js} +1 -1
- streamlit/static/static/js/{Toolbar.BXfC9Z-W.js → Toolbar.mUe2Nmta.js} +1 -1
- streamlit/static/static/js/{WidgetLabelHelpIconInline.gkreC55g.js → WidgetLabelHelpIconInline.if89y2mu.js} +1 -1
- streamlit/static/static/js/{base-input.iB32RS3w.js → base-input.AJ4KxBTh.js} +1 -1
- streamlit/static/static/js/{checkbox.Bqz68SYq.js → checkbox.GY4JoJkM.js} +1 -1
- streamlit/static/static/js/{createDownloadLinkElement.YxVC9Qur.js → createDownloadLinkElement.BWJh90jh.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.sBsdk5Xg.js → data-grid-overlay-editor.C9AINtRf.js} +1 -1
- streamlit/static/static/js/{downloader.Bzxqt3AW.js → downloader.BZY8OE4f.js} +1 -1
- streamlit/static/static/js/{embed.CDzakah3.js → embed.BjO7Ez0y.js} +1 -1
- streamlit/static/static/js/{es6.CxCc4bfn.js → es6.eb5oR8iN.js} +2 -2
- streamlit/static/static/js/{formatNumber.L8T7D36k.js → formatNumber.CCeQsvJQ.js} +1 -1
- streamlit/static/static/js/{iconPosition.C47DkA-1.js → iconPosition.D6eEnKvO.js} +1 -1
- streamlit/static/static/js/{iframeResizer.contentWindow.uEFLXEg3.js → iframeResizer.contentWindow.DTsWJRTo.js} +1 -1
- streamlit/static/static/js/{index.C6dhwBSe.js → index.B6l4FdUv.js} +1 -1
- streamlit/static/static/js/{index.BV_YgIHe.js → index.B7H2q9vo.js} +2 -2
- streamlit/static/static/js/{index.DjgdCvlK.js → index.BDdmrM58.js} +1 -1
- streamlit/static/static/js/{index.CAbQaUvi.js → index.BMbQnwRD.js} +1 -1
- streamlit/static/static/js/{index.CCLteRW6.js → index.BQ5MOzHu.js} +1 -1
- streamlit/static/static/js/{index.CzwJzgQs.js → index.BSgo_bkv.js} +1 -1
- streamlit/static/static/js/{index.B60AZFRh.js → index.BU5M9DsN.js} +1 -1
- streamlit/static/static/js/{index.BVTW_o-a.js → index.BYIxnU34.js} +1 -1
- streamlit/static/static/js/{index.DqhZqWYB.js → index.BZL2hIBz.js} +1 -1
- streamlit/static/static/js/{index.CAbafj7s.js → index.BZVrJlnq.js} +1 -1
- streamlit/static/static/js/{index.Ck0ZkOfK.js → index.Bd7QK46M.js} +1 -1
- streamlit/static/static/js/{index.BzdcdLDK.js → index.BfHA_i34.js} +1 -1
- streamlit/static/static/js/{index.kBgXO7Vv.js → index.Bgry-Ek_.js} +1 -1
- streamlit/static/static/js/{index.aZRhdEuX.js → index.Bi25zaXA.js} +1 -1
- streamlit/static/static/js/{index.QXukCzoh.js → index.Bj3M1xBC.js} +1 -1
- streamlit/static/static/js/{index.Bnwh8oZr.js → index.Bjrvlqx5.js} +6 -6
- streamlit/static/static/js/{index.h2N-W51I.js → index.BnOSeM5K.js} +1 -1
- streamlit/static/static/js/index.BoL6J1jK.js +2 -0
- streamlit/static/static/js/{index.BwvxzVOo.js → index.BoORyxOa.js} +1 -1
- streamlit/static/static/js/{index.Ba8L-ulI.js → index.Bpd7GPeH.js} +1 -1
- streamlit/static/static/js/{index.BG4RxMOI.js → index.BpeJX018.js} +1 -1
- streamlit/static/static/js/index.BriH7JVk.js +2 -0
- streamlit/static/static/js/{index.DO55kRo5.js → index.BwkeObMo.js} +1 -1
- streamlit/static/static/js/{index.C1d2QjTR.js → index.C0o85qmd.js} +1 -1
- streamlit/static/static/js/{index.D7L9gHlE.js → index.C7_wNJTH.js} +1 -1
- streamlit/static/static/js/{index.BwTkGOAy.js → index.CGZP_w9b.js} +1 -1
- streamlit/static/static/js/{index.CjBDVb1a.js → index.CGw52-0-.js} +1 -1
- streamlit/static/static/js/{index.D_cvtSlg.js → index.CUvtJj0a.js} +1 -1
- streamlit/static/static/js/{index.Dtbj_oyb.js → index.Cfx1ZHWt.js} +1 -1
- streamlit/static/static/js/{index.BvHsyiyy.js → index.Chl2kALe.js} +1 -1
- streamlit/static/static/js/index.Crlx_wdE.js +1 -0
- streamlit/static/static/js/{index.B_LfkwqU.js → index.D9A-8ebQ.js} +1 -1
- streamlit/static/static/js/{index.BHyzKS4e.js → index.DBIoNOen.js} +7 -7
- streamlit/static/static/js/{index.DgqmsDCJ.js → index.DMKTAe4F.js} +1 -1
- streamlit/static/static/js/{index.DEKnCsY-.js → index.DNrpqKVt.js} +1 -1
- streamlit/static/static/js/{index.BsrhCS7f.js → index.DSRvF_8e.js} +1 -1
- streamlit/static/static/js/{index.DN_oudQl.js → index.DhB1m_xG.js} +1 -1
- streamlit/static/static/js/{index.XJY9qZ6a.js → index.DiES30vM.js} +1 -1
- streamlit/static/static/js/{index.DHrByikW.js → index.DlJ4Y1xc.js} +1 -1
- streamlit/static/static/js/{index.C5-TpWis.js → index.J61yByUR.js} +1 -1
- streamlit/static/static/js/{index.iUHLeAvv.js → index.JxDTXE8N.js} +1 -1
- streamlit/static/static/js/{index.C1uZrWog.js → index.KGr28TP8.js} +1 -1
- streamlit/static/static/js/{index.BuJPJSD7.js → index.Pgm3rRpH.js} +1 -1
- streamlit/static/static/js/{index.fUsWkW8E.js → index.XzcYOc9I.js} +1 -1
- streamlit/static/static/js/{index.CQ713nQM.js → index.Z_u7ZS4h.js} +1 -1
- streamlit/static/static/js/{index.D-9VyyiA.js → index.hDg7x0Tp.js} +1 -1
- streamlit/static/static/js/{index.D2R3Co5f.js → index.k7p0hmaU.js} +1 -1
- streamlit/static/static/js/{index.Bh5BZaHG.js → index.syoxWolF.js} +1 -1
- streamlit/static/static/js/{index.kEL0HsUR.js → index.xZ651bTg.js} +1 -1
- streamlit/static/static/js/{input.BCHJn1Cw.js → input.C-PwAMG6.js} +1 -1
- streamlit/static/static/js/{main.23ZP6f1E.js → main.fMmyxXOf.js} +1 -1
- streamlit/static/static/js/{memory.D8f8Q4mO.js → memory.BG__eDEj.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.ZWvSpjJ5.js → number-overlay-editor.C0n-91sR.js} +1 -1
- streamlit/static/static/js/{pandasStylerUtils.DlZ2GBs_.js → pandasStylerUtils.BqWaUzvh.js} +1 -1
- streamlit/static/static/js/{sandbox.BH6D3KL9.js → sandbox.CHhc-txg.js} +1 -1
- streamlit/static/static/js/{sprintfjs.CtrdaGLQ.js → sprintfjs.BlFBKfMf.js} +1 -1
- streamlit/static/static/js/{styled-components.iD1HRMLc.js → styled-components.D5uOQqN2.js} +1 -1
- streamlit/static/static/js/{throttle.DR7d9vp_.js → throttle.DlZC3xNA.js} +1 -1
- streamlit/static/static/js/{timepicker.Bd34xjcG.js → timepicker._TfRUaDL.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.BDTTq1c5.js → toConsumableArray.CZW4AmuW.js} +1 -1
- streamlit/static/static/js/uniqueId.CTTDAAaF.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.BXKaD8DQ.js → useBasicWidgetState.Bx27912z.js} +1 -1
- streamlit/static/static/js/{useIntlLocale.CysOvegI.js → useIntlLocale.DsOvysl7.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.CVd5Hf2S.js → useTextInputAutoExpand.C9g8px1W.js} +1 -1
- streamlit/static/static/js/{useUpdateUiValue.CIUgfO8X.js → useUpdateUiValue.fF-Cntkp.js} +1 -1
- streamlit/static/static/js/{useWaveformController.CDLqlnLv.js → useWaveformController.C5EtFoJE.js} +1 -1
- streamlit/static/static/js/{withCalculatedWidth.Ce1Zblb2.js → withCalculatedWidth.CcvaXQb0.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.DBm7N75M.js → withFullScreenWrapper.DP61hzLF.js} +1 -1
- streamlit/testing/v1/element_tree.py +20 -15
- streamlit/web/server/routes.py +14 -0
- streamlit/web/server/server.py +4 -0
- {streamlit_nightly-1.53.2.dev20260203.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.53.2.dev20260203.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/RECORD +122 -120
- streamlit/proto/Arrow_pb2.py +0 -34
- streamlit/static/static/js/index.B3zULhHv.js +0 -1
- streamlit/static/static/js/index.BrZtYm2A.js +0 -2
- streamlit/static/static/js/index.CcBYyLfq.js +0 -2
- streamlit/static/static/js/uniqueId.Bd_Iuzvc.js +0 -1
- {streamlit_nightly-1.53.2.dev20260203.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.53.2.dev20260203.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.53.2.dev20260203.dist-info → streamlit_nightly-1.54.1.dev20260204.dist-info}/top_level.txt +0 -0
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
from collections.abc import Callable, Sequence
|
|
18
|
-
from dataclasses import dataclass, field
|
|
19
18
|
from typing import (
|
|
20
19
|
TYPE_CHECKING,
|
|
21
20
|
Any,
|
|
@@ -27,6 +26,7 @@ from typing import (
|
|
|
27
26
|
overload,
|
|
28
27
|
)
|
|
29
28
|
|
|
29
|
+
from streamlit.dataframe_util import convert_anything_to_list
|
|
30
30
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
31
31
|
from streamlit.elements.lib.layout_utils import (
|
|
32
32
|
LayoutConfig,
|
|
@@ -34,9 +34,12 @@ from streamlit.elements.lib.layout_utils import (
|
|
|
34
34
|
validate_width,
|
|
35
35
|
)
|
|
36
36
|
from streamlit.elements.lib.options_selector_utils import (
|
|
37
|
-
check_and_convert_to_indices,
|
|
38
37
|
convert_to_sequence_and_check_comparable,
|
|
39
38
|
get_default_indices,
|
|
39
|
+
maybe_coerce_enum,
|
|
40
|
+
maybe_coerce_enum_sequence,
|
|
41
|
+
validate_and_sync_multiselect_value_with_options,
|
|
42
|
+
validate_and_sync_value_with_options,
|
|
40
43
|
)
|
|
41
44
|
from streamlit.elements.lib.policies import (
|
|
42
45
|
check_widget_policies,
|
|
@@ -77,96 +80,150 @@ V = TypeVar("V")
|
|
|
77
80
|
SelectionMode: TypeAlias = Literal["single", "multi"]
|
|
78
81
|
|
|
79
82
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"""Only meant to be used internally for the button_group element.
|
|
83
|
+
class _SingleSelectButtonGroupSerde(Generic[T]):
|
|
84
|
+
"""String-based serde for single-select ButtonGroup widgets.
|
|
83
85
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
required by the button_group element. If this changes again at some point,
|
|
87
|
-
the two elements can share the same serde again.
|
|
86
|
+
Uses string-based values (formatted option strings) for robust handling
|
|
87
|
+
of dynamic option changes.
|
|
88
88
|
"""
|
|
89
89
|
|
|
90
90
|
options: Sequence[T]
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return indices if indices is not None else []
|
|
96
|
-
|
|
97
|
-
def deserialize(self, ui_value: list[int] | None) -> list[T]:
|
|
98
|
-
current_value: list[int] = (
|
|
99
|
-
ui_value if ui_value is not None else self.default_value
|
|
100
|
-
)
|
|
101
|
-
return [self.options[i] for i in current_value]
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
class _SingleSelectSerde(Generic[T]):
|
|
105
|
-
"""Only meant to be used internally for the button_group element.
|
|
106
|
-
|
|
107
|
-
Uses the ButtonGroup's _MultiSelectSerde under-the-hood, but accepts a single
|
|
108
|
-
index value and deserializes to a single index value.
|
|
109
|
-
This is because button_group can be single and multi select, but we use the same
|
|
110
|
-
proto for both and, thus, map single values to a list of values and a receiving
|
|
111
|
-
value wrapped in a list to a single value.
|
|
112
|
-
|
|
113
|
-
When a default_value is provided is provided, the option corresponding to the
|
|
114
|
-
index is serialized/deserialized.
|
|
115
|
-
"""
|
|
91
|
+
formatted_options: list[str]
|
|
92
|
+
formatted_option_to_option_index: dict[str, int]
|
|
93
|
+
default_option_index: int | None
|
|
94
|
+
format_func: Callable[[Any], str]
|
|
116
95
|
|
|
117
96
|
def __init__(
|
|
118
97
|
self,
|
|
119
|
-
|
|
120
|
-
|
|
98
|
+
options: Sequence[T],
|
|
99
|
+
*,
|
|
100
|
+
formatted_options: list[str],
|
|
101
|
+
formatted_option_to_option_index: dict[str, int],
|
|
102
|
+
default_option_index: int | None = None,
|
|
103
|
+
format_func: Callable[[Any], str] = str,
|
|
121
104
|
) -> None:
|
|
122
|
-
|
|
123
|
-
self.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
105
|
+
self.options = options
|
|
106
|
+
self.formatted_options = formatted_options
|
|
107
|
+
self.formatted_option_to_option_index = formatted_option_to_option_index
|
|
108
|
+
self.default_option_index = default_option_index
|
|
109
|
+
self.format_func = format_func
|
|
110
|
+
|
|
111
|
+
def serialize(self, v: T | str | None) -> list[str]:
|
|
112
|
+
"""Serialize single-select value to a list of strings for wire format."""
|
|
113
|
+
if v is None:
|
|
114
|
+
return []
|
|
115
|
+
if len(self.options) == 0:
|
|
116
|
+
return []
|
|
117
|
+
|
|
118
|
+
# First, try to find the option by value in the options list
|
|
119
|
+
for index, opt in enumerate(self.options):
|
|
120
|
+
if opt == v:
|
|
121
|
+
return [self.formatted_options[index]]
|
|
122
|
+
|
|
123
|
+
# If not found by direct comparison, try by formatted string
|
|
124
|
+
try:
|
|
125
|
+
formatted_value = self.format_func(v)
|
|
126
|
+
except Exception:
|
|
127
|
+
return [str(v)]
|
|
128
|
+
|
|
129
|
+
return [formatted_value]
|
|
130
|
+
|
|
131
|
+
def deserialize(self, ui_value: list[str] | None) -> T | str | None:
|
|
132
|
+
"""Deserialize from a list of strings to a single value."""
|
|
133
|
+
if len(self.options) == 0:
|
|
134
|
+
return None
|
|
130
135
|
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
# None means initial state - use default if available
|
|
137
|
+
if ui_value is None:
|
|
138
|
+
if self.default_option_index is not None:
|
|
139
|
+
return self.options[self.default_option_index]
|
|
140
|
+
return None
|
|
133
141
|
|
|
134
|
-
|
|
142
|
+
# Empty list means explicit deselection by user - return None
|
|
143
|
+
if len(ui_value) == 0:
|
|
135
144
|
return None
|
|
136
145
|
|
|
137
|
-
|
|
146
|
+
string_value = ui_value[0]
|
|
147
|
+
|
|
148
|
+
# Look up the option index by formatted string
|
|
149
|
+
option_index = self.formatted_option_to_option_index.get(string_value)
|
|
150
|
+
if option_index is not None:
|
|
151
|
+
return self.options[option_index]
|
|
138
152
|
|
|
153
|
+
# Value not found in options - return as-is
|
|
154
|
+
return string_value
|
|
139
155
|
|
|
140
|
-
class ButtonGroupSerde(Generic[T]):
|
|
141
|
-
"""A serde that can handle both single and multi select options.
|
|
142
156
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
157
|
+
class _MultiSelectButtonGroupSerde(Generic[T]):
|
|
158
|
+
"""String-based serde for multi-select ButtonGroup widgets.
|
|
159
|
+
|
|
160
|
+
Uses string-based values (formatted option strings) for robust handling
|
|
161
|
+
of dynamic option changes.
|
|
148
162
|
"""
|
|
149
163
|
|
|
164
|
+
options: Sequence[T]
|
|
165
|
+
formatted_options: list[str]
|
|
166
|
+
formatted_option_to_option_index: dict[str, int]
|
|
167
|
+
default_option_indices: list[int]
|
|
168
|
+
format_func: Callable[[Any], str]
|
|
169
|
+
|
|
150
170
|
def __init__(
|
|
151
171
|
self,
|
|
152
172
|
options: Sequence[T],
|
|
153
|
-
|
|
154
|
-
|
|
173
|
+
*,
|
|
174
|
+
formatted_options: list[str],
|
|
175
|
+
formatted_option_to_option_index: dict[str, int],
|
|
176
|
+
default_option_indices: list[int] | None = None,
|
|
177
|
+
format_func: Callable[[Any], str] = str,
|
|
155
178
|
) -> None:
|
|
156
179
|
self.options = options
|
|
157
|
-
self.
|
|
158
|
-
self.
|
|
159
|
-
self.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
180
|
+
self.formatted_options = formatted_options
|
|
181
|
+
self.formatted_option_to_option_index = formatted_option_to_option_index
|
|
182
|
+
self.default_option_indices = default_option_indices or []
|
|
183
|
+
self.format_func = format_func
|
|
184
|
+
|
|
185
|
+
def serialize(self, value: list[T | str] | list[T] | None) -> list[str]:
|
|
186
|
+
"""Serialize multi-select values to list of strings for wire format."""
|
|
187
|
+
if value is None:
|
|
188
|
+
return []
|
|
189
|
+
converted_value = convert_anything_to_list(value)
|
|
190
|
+
values: list[str] = []
|
|
191
|
+
for v in converted_value:
|
|
192
|
+
# First, try to find the option by value in the options list
|
|
193
|
+
found = False
|
|
194
|
+
for index, opt in enumerate(self.options):
|
|
195
|
+
if opt == v:
|
|
196
|
+
values.append(self.formatted_options[index])
|
|
197
|
+
found = True
|
|
198
|
+
break
|
|
199
|
+
|
|
200
|
+
if found:
|
|
201
|
+
continue
|
|
202
|
+
|
|
203
|
+
# If not found by direct comparison, try by formatted string
|
|
204
|
+
try:
|
|
205
|
+
formatted_value = self.format_func(v)
|
|
206
|
+
except Exception:
|
|
207
|
+
values.append(str(v))
|
|
208
|
+
continue
|
|
209
|
+
|
|
210
|
+
values.append(formatted_value)
|
|
211
|
+
return values
|
|
212
|
+
|
|
213
|
+
def deserialize(self, ui_value: list[str] | None) -> list[T | str] | list[T]:
|
|
214
|
+
"""Deserialize from list of strings to list of values."""
|
|
215
|
+
if ui_value is None:
|
|
216
|
+
return [self.options[i] for i in self.default_option_indices]
|
|
217
|
+
|
|
218
|
+
values: list[T | str] = []
|
|
219
|
+
for v in ui_value:
|
|
220
|
+
option_index = self.formatted_option_to_option_index.get(v)
|
|
221
|
+
if option_index is not None:
|
|
222
|
+
values.append(self.options[option_index])
|
|
223
|
+
else:
|
|
224
|
+
# Value not found in options - append as-is
|
|
225
|
+
values.append(v)
|
|
226
|
+
return values
|
|
170
227
|
|
|
171
228
|
|
|
172
229
|
def _build_proto(
|
|
@@ -695,11 +752,14 @@ class ButtonGroupMixin:
|
|
|
695
752
|
) -> list[V] | V | None:
|
|
696
753
|
maybe_raise_label_warnings(label, label_visibility)
|
|
697
754
|
|
|
755
|
+
# Use str as default format_func
|
|
756
|
+
actual_format_func: Callable[[Any], str] = format_func or str
|
|
757
|
+
|
|
698
758
|
def _transformed_format_func(option: V) -> ButtonGroupProto.Option:
|
|
699
759
|
"""If option starts with a material icon or an emoji, we extract it to send
|
|
700
760
|
it parsed to the frontend.
|
|
701
761
|
"""
|
|
702
|
-
transformed =
|
|
762
|
+
transformed = actual_format_func(option)
|
|
703
763
|
transformed_parts = transformed.split(" ")
|
|
704
764
|
icon: str | None = None
|
|
705
765
|
if len(transformed_parts) > 0:
|
|
@@ -725,11 +785,42 @@ class ButtonGroupMixin:
|
|
|
725
785
|
indexable_options = convert_to_sequence_and_check_comparable(options)
|
|
726
786
|
default_values = get_default_indices(indexable_options, default)
|
|
727
787
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
788
|
+
# Create string-based mappings for the serde
|
|
789
|
+
formatted_options: list[str] = []
|
|
790
|
+
formatted_option_to_option_index: dict[str, int] = {}
|
|
791
|
+
for index, option in enumerate(indexable_options):
|
|
792
|
+
formatted = actual_format_func(option)
|
|
793
|
+
formatted_options.append(formatted)
|
|
794
|
+
# If formatted labels are duplicated, the last one wins. We keep this
|
|
795
|
+
# behavior to mirror radio/selectbox/multiselect.
|
|
796
|
+
formatted_option_to_option_index[formatted] = index
|
|
797
|
+
|
|
798
|
+
# Create appropriate serde based on selection mode
|
|
799
|
+
serializer: WidgetSerializer[Any]
|
|
800
|
+
deserializer: WidgetDeserializer[Any]
|
|
801
|
+
if selection_mode == "multi":
|
|
802
|
+
multi_serde = _MultiSelectButtonGroupSerde[V](
|
|
803
|
+
indexable_options,
|
|
804
|
+
formatted_options=formatted_options,
|
|
805
|
+
formatted_option_to_option_index=formatted_option_to_option_index,
|
|
806
|
+
default_option_indices=default_values,
|
|
807
|
+
format_func=actual_format_func,
|
|
808
|
+
)
|
|
809
|
+
serializer = multi_serde.serialize
|
|
810
|
+
deserializer = multi_serde.deserialize
|
|
811
|
+
else:
|
|
812
|
+
single_serde = _SingleSelectButtonGroupSerde[V](
|
|
813
|
+
indexable_options,
|
|
814
|
+
formatted_options=formatted_options,
|
|
815
|
+
formatted_option_to_option_index=formatted_option_to_option_index,
|
|
816
|
+
default_option_index=default_values[0] if default_values else None,
|
|
817
|
+
format_func=actual_format_func,
|
|
818
|
+
)
|
|
819
|
+
serializer = single_serde.serialize
|
|
820
|
+
deserializer = single_serde.deserialize
|
|
731
821
|
|
|
732
|
-
|
|
822
|
+
# Single call to _button_group with the appropriate serde
|
|
823
|
+
result: RegisterWidgetResult[Any] = self._button_group(
|
|
733
824
|
indexable_options,
|
|
734
825
|
default=default_values,
|
|
735
826
|
selection_mode=selection_mode,
|
|
@@ -738,20 +829,28 @@ class ButtonGroupMixin:
|
|
|
738
829
|
key=key,
|
|
739
830
|
help=help,
|
|
740
831
|
style=style,
|
|
741
|
-
serializer=
|
|
742
|
-
deserializer=
|
|
832
|
+
serializer=serializer,
|
|
833
|
+
deserializer=deserializer,
|
|
743
834
|
on_change=on_change,
|
|
744
835
|
args=args,
|
|
745
836
|
kwargs=kwargs,
|
|
746
837
|
label=label,
|
|
747
838
|
label_visibility=label_visibility,
|
|
748
839
|
width=width,
|
|
840
|
+
options_format_func=actual_format_func,
|
|
749
841
|
)
|
|
750
842
|
|
|
843
|
+
# Handle return type based on selection mode
|
|
751
844
|
if selection_mode == "multi":
|
|
752
|
-
|
|
845
|
+
multi_res = cast("RegisterWidgetResult[list[V] | list[V | str]]", result)
|
|
846
|
+
multi_res = maybe_coerce_enum_sequence(
|
|
847
|
+
multi_res, options, indexable_options
|
|
848
|
+
)
|
|
849
|
+
return cast("list[V]", multi_res.value)
|
|
753
850
|
|
|
754
|
-
|
|
851
|
+
single_res = cast("RegisterWidgetResult[V | str | None]", result)
|
|
852
|
+
single_res = maybe_coerce_enum(single_res, options, indexable_options)
|
|
853
|
+
return cast("V | None", single_res.value)
|
|
755
854
|
|
|
756
855
|
def _button_group(
|
|
757
856
|
self,
|
|
@@ -772,6 +871,7 @@ class ButtonGroupMixin:
|
|
|
772
871
|
label_visibility: LabelVisibility = "visible",
|
|
773
872
|
help: str | None = None,
|
|
774
873
|
width: Width = "content",
|
|
874
|
+
options_format_func: Callable[[Any], str] | None = None,
|
|
775
875
|
) -> RegisterWidgetResult[T]:
|
|
776
876
|
_maybe_raise_selection_mode_warning(selection_mode)
|
|
777
877
|
|
|
@@ -826,10 +926,7 @@ class ButtonGroupMixin:
|
|
|
826
926
|
element_id = compute_and_register_element_id(
|
|
827
927
|
style,
|
|
828
928
|
user_key=key,
|
|
829
|
-
|
|
830
|
-
# and only include kwargs that can invalidate the current selection.
|
|
831
|
-
# We whitelist the formatted options and the click mode (single vs multi).
|
|
832
|
-
key_as_main_identity={"options", "click_mode"},
|
|
929
|
+
key_as_main_identity={"click_mode"},
|
|
833
930
|
dg=self.dg,
|
|
834
931
|
options=formatted_options,
|
|
835
932
|
default=default,
|
|
@@ -861,11 +958,40 @@ class ButtonGroupMixin:
|
|
|
861
958
|
deserializer=deserializer,
|
|
862
959
|
serializer=serializer,
|
|
863
960
|
ctx=ctx,
|
|
864
|
-
value_type="
|
|
961
|
+
value_type="string_array_value",
|
|
865
962
|
)
|
|
866
963
|
|
|
867
|
-
|
|
868
|
-
|
|
964
|
+
# Validate and sync value with options for pills/segmented_control
|
|
965
|
+
value_needs_reset = False
|
|
966
|
+
current_value: T | list[T] | list[T | str] | None = widget_state.value
|
|
967
|
+
if options_format_func is not None:
|
|
968
|
+
if selection_mode == "single":
|
|
969
|
+
# Single select: validate and possibly reset to default
|
|
970
|
+
default_index = default[0] if default else None
|
|
971
|
+
current_value, value_needs_reset = validate_and_sync_value_with_options(
|
|
972
|
+
cast("T | None", widget_state.value),
|
|
973
|
+
indexable_options,
|
|
974
|
+
default_index,
|
|
975
|
+
key,
|
|
976
|
+
options_format_func,
|
|
977
|
+
)
|
|
978
|
+
else:
|
|
979
|
+
# Multi select: filter out invalid values
|
|
980
|
+
current_value, value_needs_reset = (
|
|
981
|
+
validate_and_sync_multiselect_value_with_options(
|
|
982
|
+
cast("list[T] | list[T | str]", widget_state.value),
|
|
983
|
+
indexable_options,
|
|
984
|
+
key,
|
|
985
|
+
options_format_func,
|
|
986
|
+
)
|
|
987
|
+
)
|
|
988
|
+
|
|
989
|
+
if value_needs_reset or widget_state.value_changed:
|
|
990
|
+
# Always use string-based raw_values field
|
|
991
|
+
value_for_serialization = (
|
|
992
|
+
current_value if value_needs_reset else widget_state.value
|
|
993
|
+
)
|
|
994
|
+
proto.raw_values[:] = serializer(cast("T", value_for_serialization))
|
|
869
995
|
proto.set_value = True
|
|
870
996
|
|
|
871
997
|
if ctx:
|
|
@@ -873,6 +999,15 @@ class ButtonGroupMixin:
|
|
|
873
999
|
|
|
874
1000
|
self.dg._enqueue("button_group", proto, layout_config=layout_config)
|
|
875
1001
|
|
|
1002
|
+
# Return widget_state with possibly updated value
|
|
1003
|
+
if value_needs_reset:
|
|
1004
|
+
from streamlit.runtime.state.common import RegisterWidgetResult
|
|
1005
|
+
|
|
1006
|
+
return RegisterWidgetResult(
|
|
1007
|
+
cast("T", current_value),
|
|
1008
|
+
widget_state.value_changed or value_needs_reset,
|
|
1009
|
+
)
|
|
1010
|
+
|
|
876
1011
|
return widget_state
|
|
877
1012
|
|
|
878
1013
|
@property
|
|
@@ -63,7 +63,7 @@ from streamlit.elements.lib.pandas_styler_utils import marshall_styler
|
|
|
63
63
|
from streamlit.elements.lib.policies import check_widget_policies
|
|
64
64
|
from streamlit.elements.lib.utils import Key, compute_and_register_element_id, to_key
|
|
65
65
|
from streamlit.errors import StreamlitAPIException
|
|
66
|
-
from streamlit.proto.
|
|
66
|
+
from streamlit.proto.Dataframe_pb2 import Dataframe as DataframeProto
|
|
67
67
|
from streamlit.runtime.metrics_util import gather_metrics
|
|
68
68
|
from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
|
|
69
69
|
from streamlit.runtime.state import (
|
|
@@ -1093,7 +1093,7 @@ class DataEditorMixin:
|
|
|
1093
1093
|
placeholder=placeholder,
|
|
1094
1094
|
)
|
|
1095
1095
|
|
|
1096
|
-
proto =
|
|
1096
|
+
proto = DataframeProto()
|
|
1097
1097
|
proto.id = element_id
|
|
1098
1098
|
|
|
1099
1099
|
if row_height:
|
|
@@ -1110,13 +1110,13 @@ class DataEditorMixin:
|
|
|
1110
1110
|
proto.disabled = disabled is True
|
|
1111
1111
|
|
|
1112
1112
|
if num_rows == "dynamic":
|
|
1113
|
-
proto.editing_mode =
|
|
1113
|
+
proto.editing_mode = DataframeProto.EditingMode.DYNAMIC
|
|
1114
1114
|
elif num_rows == "add":
|
|
1115
|
-
proto.editing_mode =
|
|
1115
|
+
proto.editing_mode = DataframeProto.EditingMode.ADD_ONLY
|
|
1116
1116
|
elif num_rows == "delete":
|
|
1117
|
-
proto.editing_mode =
|
|
1117
|
+
proto.editing_mode = DataframeProto.EditingMode.DELETE_ONLY
|
|
1118
1118
|
else:
|
|
1119
|
-
proto.editing_mode =
|
|
1119
|
+
proto.editing_mode = DataframeProto.EditingMode.FIXED
|
|
1120
1120
|
|
|
1121
1121
|
proto.form_id = current_form_id(self.dg)
|
|
1122
1122
|
|
|
@@ -1132,9 +1132,9 @@ class DataEditorMixin:
|
|
|
1132
1132
|
# rendering in the data editor.
|
|
1133
1133
|
styler_uuid = calc_md5(key or self.dg._get_delta_path_str())[:10]
|
|
1134
1134
|
data.set_uuid(styler_uuid) # ty: ignore[call-non-callable, possibly-missing-attribute]
|
|
1135
|
-
marshall_styler(proto, data, styler_uuid)
|
|
1135
|
+
marshall_styler(proto.arrow_data, data, styler_uuid)
|
|
1136
1136
|
|
|
1137
|
-
proto.data = arrow_bytes
|
|
1137
|
+
proto.arrow_data.data = arrow_bytes
|
|
1138
1138
|
|
|
1139
1139
|
marshall_column_config(proto, column_config_mapping)
|
|
1140
1140
|
|
|
@@ -1159,7 +1159,7 @@ class DataEditorMixin:
|
|
|
1159
1159
|
)
|
|
1160
1160
|
|
|
1161
1161
|
_apply_dataframe_edits(data_df, widget_state.value, dataframe_schema)
|
|
1162
|
-
self.dg._enqueue("
|
|
1162
|
+
self.dg._enqueue("dataframe", proto, layout_config=layout_config)
|
|
1163
1163
|
return dataframe_util.convert_pandas_df_to_data_format(data_df, data_format)
|
|
1164
1164
|
|
|
1165
1165
|
@property
|
|
@@ -108,13 +108,17 @@ class RadioSerde(Generic[T]):
|
|
|
108
108
|
formatted_value = self.format_func(v)
|
|
109
109
|
except Exception:
|
|
110
110
|
# format_func failed (e.g., v is a string but format_func expects
|
|
111
|
-
# an object with specific attributes).
|
|
112
|
-
|
|
111
|
+
# an object with specific attributes). Use str(v) to ensure we return
|
|
112
|
+
# a proper string, not the original object. This handles both cases:
|
|
113
|
+
# - v is already a string -> str(v) returns it unchanged
|
|
114
|
+
# - v is a custom object -> str(v) gives its string representation
|
|
115
|
+
return str(v)
|
|
113
116
|
|
|
114
117
|
if formatted_value in self.formatted_option_to_option_index:
|
|
115
118
|
return formatted_value
|
|
116
|
-
# Value not found in options - return
|
|
117
|
-
return
|
|
119
|
+
# Value not found in options - return the formatted string (not the original
|
|
120
|
+
# object) to maintain type consistency since serialize() must return str|None
|
|
121
|
+
return formatted_value
|
|
118
122
|
|
|
119
123
|
def deserialize(self, ui_value: str | None) -> T | str | None:
|
|
120
124
|
# If no options, there's no valid value - return None
|
|
@@ -26,7 +26,7 @@ def data_frame_demo() -> None:
|
|
|
26
26
|
def get_un_data() -> pd.DataFrame:
|
|
27
27
|
aws_bucket_url = "https://streamlit-demo-data.s3-us-west-2.amazonaws.com"
|
|
28
28
|
df = pd.read_csv(aws_bucket_url + "/agri.csv.gz")
|
|
29
|
-
return df.set_index("Region")
|
|
29
|
+
return df.set_index("Region") # type: ignore[no-any-return, unused-ignore]
|
|
30
30
|
|
|
31
31
|
try:
|
|
32
32
|
df = get_un_data()
|
streamlit/proto/ArrowData_pb2.py
CHANGED
|
@@ -14,13 +14,15 @@ _sym_db = _symbol_database.Default()
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fstreamlit/proto/ArrowData.proto\"\
|
|
17
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fstreamlit/proto/ArrowData.proto\"\x99\x01\n\tArrowData\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x12\'\n\x06styler\x18\x02 \x01(\x0b\x32\x17.ArrowData.PandasStyler\x1aU\n\x0cPandasStyler\x12\x0c\n\x04uuid\x18\x01 \x01(\t\x12\x0f\n\x07\x63\x61ption\x18\x02 \x01(\t\x12\x0e\n\x06styles\x18\x03 \x01(\t\x12\x16\n\x0e\x64isplay_values\x18\x04 \x01(\x0c\x62\x06proto3')
|
|
18
18
|
|
|
19
19
|
_globals = globals()
|
|
20
20
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
21
21
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'streamlit.proto.ArrowData_pb2', _globals)
|
|
22
22
|
if not _descriptor._USE_C_DESCRIPTORS:
|
|
23
23
|
DESCRIPTOR._loaded_options = None
|
|
24
|
-
_globals['_ARROWDATA']._serialized_start=
|
|
25
|
-
_globals['_ARROWDATA']._serialized_end=
|
|
24
|
+
_globals['_ARROWDATA']._serialized_start=36
|
|
25
|
+
_globals['_ARROWDATA']._serialized_end=189
|
|
26
|
+
_globals['_ARROWDATA_PANDASSTYLER']._serialized_start=104
|
|
27
|
+
_globals['_ARROWDATA_PANDASSTYLER']._serialized_end=189
|
|
26
28
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -32,22 +32,62 @@ DESCRIPTOR: _descriptor.FileDescriptor
|
|
|
32
32
|
|
|
33
33
|
@_typing.final
|
|
34
34
|
class ArrowData(_message.Message):
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
only the serialized Arrow data is required.
|
|
35
|
+
"""Arrow data buffer with optional styling. Use this message for serialized
|
|
36
|
+
Arrow data, with optional pandas styling for table-like displays.
|
|
38
37
|
"""
|
|
39
38
|
|
|
40
39
|
DESCRIPTOR: _descriptor.Descriptor
|
|
41
40
|
|
|
41
|
+
@_typing.final
|
|
42
|
+
class PandasStyler(_message.Message):
|
|
43
|
+
"""Pandas Styler information for formatting and styling table displays."""
|
|
44
|
+
|
|
45
|
+
DESCRIPTOR: _descriptor.Descriptor
|
|
46
|
+
|
|
47
|
+
UUID_FIELD_NUMBER: _builtins.int
|
|
48
|
+
CAPTION_FIELD_NUMBER: _builtins.int
|
|
49
|
+
STYLES_FIELD_NUMBER: _builtins.int
|
|
50
|
+
DISPLAY_VALUES_FIELD_NUMBER: _builtins.int
|
|
51
|
+
uuid: _builtins.str
|
|
52
|
+
"""The Styler's source UUID (if the user provided one), or the path-based
|
|
53
|
+
hash that we generate (if no source UUID was provided).
|
|
54
|
+
"""
|
|
55
|
+
caption: _builtins.str
|
|
56
|
+
"""The table's caption."""
|
|
57
|
+
styles: _builtins.str
|
|
58
|
+
"""`styles` contains the CSS for the entire source table."""
|
|
59
|
+
display_values: _builtins.bytes
|
|
60
|
+
"""display_values is another Arrow/Table: a copy of the source table, but
|
|
61
|
+
with all the display values formatted to the user-specified rules.
|
|
62
|
+
"""
|
|
63
|
+
def __init__(
|
|
64
|
+
self,
|
|
65
|
+
*,
|
|
66
|
+
uuid: _builtins.str = ...,
|
|
67
|
+
caption: _builtins.str = ...,
|
|
68
|
+
styles: _builtins.str = ...,
|
|
69
|
+
display_values: _builtins.bytes = ...,
|
|
70
|
+
) -> None: ...
|
|
71
|
+
_ClearFieldArgType: _TypeAlias = _typing.Literal["caption", b"caption", "display_values", b"display_values", "styles", b"styles", "uuid", b"uuid"] # noqa: Y015
|
|
72
|
+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
|
|
73
|
+
|
|
42
74
|
DATA_FIELD_NUMBER: _builtins.int
|
|
75
|
+
STYLER_FIELD_NUMBER: _builtins.int
|
|
43
76
|
data: _builtins.bytes
|
|
44
77
|
"""The serialized Apache Arrow buffer (IPC stream or file format bytes)"""
|
|
78
|
+
@_builtins.property
|
|
79
|
+
def styler(self) -> Global___ArrowData.PandasStyler:
|
|
80
|
+
"""Optional pandas styler information (used by table-like displays)"""
|
|
81
|
+
|
|
45
82
|
def __init__(
|
|
46
83
|
self,
|
|
47
84
|
*,
|
|
48
85
|
data: _builtins.bytes = ...,
|
|
86
|
+
styler: Global___ArrowData.PandasStyler | None = ...,
|
|
49
87
|
) -> None: ...
|
|
50
|
-
|
|
88
|
+
_HasFieldArgType: _TypeAlias = _typing.Literal["styler", b"styler"] # noqa: Y015
|
|
89
|
+
def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ...
|
|
90
|
+
_ClearFieldArgType: _TypeAlias = _typing.Literal["data", b"data", "styler", b"styler"] # noqa: Y015
|
|
51
91
|
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
|
|
52
92
|
|
|
53
93
|
Global___ArrowData: _TypeAlias = ArrowData # noqa: Y015
|
|
@@ -12,16 +12,16 @@ from google.protobuf.internal import builder as _builder
|
|
|
12
12
|
_sym_db = _symbol_database.Default()
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
from streamlit.proto import
|
|
15
|
+
from streamlit.proto import ArrowData_pb2 as streamlit_dot_proto_dot_ArrowData__pb2
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'streamlit/proto/ArrowNamedDataSet.proto\x1a\
|
|
18
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'streamlit/proto/ArrowNamedDataSet.proto\x1a\x1fstreamlit/proto/ArrowData.proto\"M\n\x11\x41rrowNamedDataSet\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08has_name\x18\x03 \x01(\x08\x12\x18\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\n.ArrowDatab\x06proto3')
|
|
19
19
|
|
|
20
20
|
_globals = globals()
|
|
21
21
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
22
22
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'streamlit.proto.ArrowNamedDataSet_pb2', _globals)
|
|
23
23
|
if not _descriptor._USE_C_DESCRIPTORS:
|
|
24
24
|
DESCRIPTOR._loaded_options = None
|
|
25
|
-
_globals['_ARROWNAMEDDATASET']._serialized_start=
|
|
26
|
-
_globals['_ARROWNAMEDDATASET']._serialized_end=
|
|
25
|
+
_globals['_ARROWNAMEDDATASET']._serialized_start=76
|
|
26
|
+
_globals['_ARROWNAMEDDATASET']._serialized_end=153
|
|
27
27
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -19,7 +19,7 @@ limitations under the License.
|
|
|
19
19
|
|
|
20
20
|
from google.protobuf import descriptor as _descriptor
|
|
21
21
|
from google.protobuf import message as _message
|
|
22
|
-
from streamlit.proto import
|
|
22
|
+
from streamlit.proto import ArrowData_pb2 as _ArrowData_pb2
|
|
23
23
|
import builtins as _builtins
|
|
24
24
|
import sys
|
|
25
25
|
import typing as _typing
|
|
@@ -47,7 +47,7 @@ class ArrowNamedDataSet(_message.Message):
|
|
|
47
47
|
around proto3 not having a way to check whether something was set.
|
|
48
48
|
"""
|
|
49
49
|
@_builtins.property
|
|
50
|
-
def data(self) ->
|
|
50
|
+
def data(self) -> _ArrowData_pb2.ArrowData:
|
|
51
51
|
"""The data itself."""
|
|
52
52
|
|
|
53
53
|
def __init__(
|
|
@@ -55,7 +55,7 @@ class ArrowNamedDataSet(_message.Message):
|
|
|
55
55
|
*,
|
|
56
56
|
name: _builtins.str = ...,
|
|
57
57
|
has_name: _builtins.bool = ...,
|
|
58
|
-
data:
|
|
58
|
+
data: _ArrowData_pb2.ArrowData | None = ...,
|
|
59
59
|
) -> None: ...
|
|
60
60
|
_HasFieldArgType: _TypeAlias = _typing.Literal["data", b"data"] # noqa: Y015
|
|
61
61
|
def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ...
|