streamlit-nightly 1.34.1.dev20240513__py2.py3-none-any.whl → 1.34.1.dev20240514__py2.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/delta_generator.py +4 -4
- streamlit/elements/arrow.py +4 -4
- streamlit/elements/plotly_chart.py +4 -4
- streamlit/elements/vega_charts.py +410 -47
- streamlit/proto/ArrowVegaLiteChart_pb2.py +2 -2
- streamlit/proto/ArrowVegaLiteChart_pb2.pyi +15 -2
- streamlit/runtime/state/common.py +3 -1
- streamlit/runtime/state/widgets.py +1 -0
- streamlit/static/asset-manifest.json +5 -5
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/1168.14f7c6ff.chunk.js +1 -0
- streamlit/static/static/js/5441.1b94928f.chunk.js +1 -0
- streamlit/static/static/js/{8148.cc5b50d8.chunk.js → 8148.a5f74d47.chunk.js} +1 -1
- streamlit/static/static/js/{main.45247b52.js → main.32c71338.js} +2 -2
- {streamlit_nightly-1.34.1.dev20240513.dist-info → streamlit_nightly-1.34.1.dev20240514.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.34.1.dev20240513.dist-info → streamlit_nightly-1.34.1.dev20240514.dist-info}/RECORD +21 -21
- streamlit/static/static/js/1168.7452e363.chunk.js +0 -1
- streamlit/static/static/js/5441.5bacdeda.chunk.js +0 -1
- /streamlit/static/static/js/{main.45247b52.js.LICENSE.txt → main.32c71338.js.LICENSE.txt} +0 -0
- {streamlit_nightly-1.34.1.dev20240513.data → streamlit_nightly-1.34.1.dev20240514.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.34.1.dev20240513.dist-info → streamlit_nightly-1.34.1.dev20240514.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.34.1.dev20240513.dist-info → streamlit_nightly-1.34.1.dev20240514.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.34.1.dev20240513.dist-info → streamlit_nightly-1.34.1.dev20240514.dist-info}/top_level.txt +0 -0
@@ -20,7 +20,20 @@ import hashlib
|
|
20
20
|
import json
|
21
21
|
import re
|
22
22
|
from contextlib import nullcontext
|
23
|
-
from
|
23
|
+
from dataclasses import dataclass
|
24
|
+
from typing import (
|
25
|
+
TYPE_CHECKING,
|
26
|
+
Any,
|
27
|
+
Final,
|
28
|
+
Iterable,
|
29
|
+
Literal,
|
30
|
+
Sequence,
|
31
|
+
TypedDict,
|
32
|
+
cast,
|
33
|
+
overload,
|
34
|
+
)
|
35
|
+
|
36
|
+
from typing_extensions import TypeAlias
|
24
37
|
|
25
38
|
import streamlit.elements.lib.dicttools as dicttools
|
26
39
|
from streamlit import type_util
|
@@ -29,11 +42,16 @@ from streamlit.elements.lib.built_in_chart_utils import (
|
|
29
42
|
ChartType,
|
30
43
|
generate_chart,
|
31
44
|
)
|
45
|
+
from streamlit.elements.lib.event_utils import AttributeDictionary
|
32
46
|
from streamlit.errors import StreamlitAPIException
|
33
47
|
from streamlit.proto.ArrowVegaLiteChart_pb2 import (
|
34
48
|
ArrowVegaLiteChart as ArrowVegaLiteChartProto,
|
35
49
|
)
|
36
50
|
from streamlit.runtime.metrics_util import gather_metrics
|
51
|
+
from streamlit.runtime.scriptrunner import get_script_run_ctx
|
52
|
+
from streamlit.runtime.state import register_widget
|
53
|
+
from streamlit.runtime.state.common import compute_widget_id
|
54
|
+
from streamlit.type_util import Key, to_key
|
37
55
|
from streamlit.util import HASHLIB_KWARGS
|
38
56
|
|
39
57
|
if TYPE_CHECKING:
|
@@ -42,6 +60,7 @@ if TYPE_CHECKING:
|
|
42
60
|
from streamlit.color_util import Color
|
43
61
|
from streamlit.delta_generator import DeltaGenerator
|
44
62
|
from streamlit.elements.arrow import Data
|
63
|
+
from streamlit.runtime.state import WidgetCallback
|
45
64
|
|
46
65
|
# See https://vega.github.io/vega-lite/docs/encoding.html
|
47
66
|
_CHANNELS: Final = {
|
@@ -73,18 +92,55 @@ _CHANNELS: Final = {
|
|
73
92
|
"column",
|
74
93
|
}
|
75
94
|
|
95
|
+
VegaLiteSpec: TypeAlias = "dict[str, Any]"
|
96
|
+
|
97
|
+
|
98
|
+
class VegaLiteState(TypedDict, total=False):
|
99
|
+
"""
|
100
|
+
A dictionary representing the current selection state of the VegaLite chart.
|
101
|
+
Attributes
|
102
|
+
----------
|
103
|
+
selection : AttributeDictionary
|
104
|
+
The state of the `on_select` event.
|
105
|
+
"""
|
106
|
+
|
107
|
+
selection: AttributeDictionary
|
108
|
+
|
109
|
+
|
110
|
+
@dataclass
|
111
|
+
class VegaLiteStateSerde:
|
112
|
+
"""VegaLiteStateSerde is used to serialize and deserialize the VegaLite Chart state."""
|
113
|
+
|
114
|
+
selection_parameters: Sequence[str]
|
115
|
+
|
116
|
+
def deserialize(self, ui_value: str | None, widget_id: str = "") -> VegaLiteState:
|
117
|
+
empty_selection_state: VegaLiteState = {
|
118
|
+
"selection": AttributeDictionary(
|
119
|
+
# Initialize the select state with empty dictionaries for each selection parameter.
|
120
|
+
{param: {} for param in self.selection_parameters}
|
121
|
+
),
|
122
|
+
}
|
123
|
+
|
124
|
+
selection_state = (
|
125
|
+
empty_selection_state
|
126
|
+
if ui_value is None
|
127
|
+
else cast(VegaLiteState, AttributeDictionary(json.loads(ui_value)))
|
128
|
+
)
|
129
|
+
|
130
|
+
if "selection" not in selection_state:
|
131
|
+
selection_state = empty_selection_state
|
132
|
+
|
133
|
+
return cast(VegaLiteState, AttributeDictionary(selection_state))
|
134
|
+
|
135
|
+
def serialize(self, selection_state: VegaLiteState) -> str:
|
136
|
+
return json.dumps(selection_state, default=str)
|
137
|
+
|
76
138
|
|
77
139
|
def _prepare_vega_lite_spec(
|
78
|
-
spec:
|
140
|
+
spec: VegaLiteSpec,
|
79
141
|
use_container_width: bool = False,
|
80
142
|
**kwargs,
|
81
|
-
) ->
|
82
|
-
# Support passing no spec arg, but filling it with kwargs.
|
83
|
-
# Example:
|
84
|
-
# marshall(proto, baz='boz')
|
85
|
-
if spec is None:
|
86
|
-
spec = dict()
|
87
|
-
|
143
|
+
) -> VegaLiteSpec:
|
88
144
|
if len(kwargs):
|
89
145
|
# Support passing in kwargs. Example:
|
90
146
|
# marshall(proto, {foo: 'bar'}, baz='boz')
|
@@ -124,7 +180,7 @@ def _serialize_data(data: Any) -> bytes:
|
|
124
180
|
|
125
181
|
def _marshall_chart_data(
|
126
182
|
proto: ArrowVegaLiteChartProto,
|
127
|
-
spec:
|
183
|
+
spec: VegaLiteSpec,
|
128
184
|
data: Data = None,
|
129
185
|
) -> None:
|
130
186
|
"""Adds the data to the proto and removes it from the spec dict.
|
@@ -172,7 +228,7 @@ def _marshall_chart_data(
|
|
172
228
|
proto.data.data = _serialize_data(data)
|
173
229
|
|
174
230
|
|
175
|
-
def _convert_altair_to_vega_lite_spec(altair_chart: alt.Chart) ->
|
231
|
+
def _convert_altair_to_vega_lite_spec(altair_chart: alt.Chart) -> VegaLiteSpec:
|
176
232
|
"""Convert an Altair chart object to a Vega-Lite chart spec."""
|
177
233
|
import altair as alt
|
178
234
|
|
@@ -189,7 +245,6 @@ def _convert_altair_to_vega_lite_spec(altair_chart: alt.Chart) -> dict[str, Any]
|
|
189
245
|
stores the bytes into the datasets mapping and
|
190
246
|
returns this name to have it be used in Altair.
|
191
247
|
"""
|
192
|
-
|
193
248
|
# Already serialize the data to be able to create a stable
|
194
249
|
# dataset name:
|
195
250
|
data_bytes = _serialize_data(data)
|
@@ -215,6 +270,97 @@ def _convert_altair_to_vega_lite_spec(altair_chart: alt.Chart) -> dict[str, Any]
|
|
215
270
|
return chart_dict
|
216
271
|
|
217
272
|
|
273
|
+
def _disallow_multi_view_charts(spec: VegaLiteSpec) -> None:
|
274
|
+
"""Raise an exception if the spec contains a multi-view chart (view composition).
|
275
|
+
|
276
|
+
This is intended to be used as a temporary solution to prevent selections on
|
277
|
+
multi-view charts. There are too many edge cases to handle selections on these
|
278
|
+
charts correctly, so we're disallowing them for now.
|
279
|
+
|
280
|
+
More information about view compositions: https://vega.github.io/vega-lite/docs/composition.html
|
281
|
+
"""
|
282
|
+
|
283
|
+
if (
|
284
|
+
any(key in spec for key in ["layer", "hconcat", "vconcat", "concat", "spec"])
|
285
|
+
or "encoding" not in spec
|
286
|
+
):
|
287
|
+
raise StreamlitAPIException(
|
288
|
+
"Selections are not yet supported for multi-view charts (chart compositions). "
|
289
|
+
"If you would like to use selections on multi-view charts, please upvote "
|
290
|
+
"this [Github issue](https://github.com/streamlit/streamlit/issues/8643)."
|
291
|
+
)
|
292
|
+
|
293
|
+
|
294
|
+
def _extract_selection_parameters(spec: VegaLiteSpec) -> set[str]:
|
295
|
+
"""Extract the names of all valid selection parameters from the spec."""
|
296
|
+
if not spec or "params" not in spec:
|
297
|
+
return set()
|
298
|
+
|
299
|
+
param_names = set()
|
300
|
+
|
301
|
+
for param in spec["params"]:
|
302
|
+
# Check if it looks like a valid selection parameter:
|
303
|
+
# https://vega.github.io/vega-lite/docs/selection.html
|
304
|
+
if param.get("name") and param.get("select"):
|
305
|
+
# Selection found, just return here to not show the exception.
|
306
|
+
param_names.add(param["name"])
|
307
|
+
|
308
|
+
return param_names
|
309
|
+
|
310
|
+
|
311
|
+
def _parse_selection_mode(
|
312
|
+
spec: VegaLiteSpec,
|
313
|
+
selection_mode: str | Iterable[str] | None,
|
314
|
+
) -> list[str]:
|
315
|
+
"""Parse and check the user provided selection modes.
|
316
|
+
|
317
|
+
This will raise an exception if no valid selection parameters are found in the spec
|
318
|
+
or if the user provided selection modes are not defined in the spec.
|
319
|
+
|
320
|
+
Parameters
|
321
|
+
----------
|
322
|
+
spec : VegaLiteSpec
|
323
|
+
The Vega-Lite chart specification.
|
324
|
+
|
325
|
+
selection_mode : str, Iterable[str], or None
|
326
|
+
The user provided selection mode(s).
|
327
|
+
|
328
|
+
Returns
|
329
|
+
-------
|
330
|
+
list[str]
|
331
|
+
The parsed selection mode(s) that should be activated.
|
332
|
+
"""
|
333
|
+
|
334
|
+
# Extract all selection parameters from the spec:
|
335
|
+
all_selection_params = _extract_selection_parameters(spec)
|
336
|
+
|
337
|
+
if not all_selection_params:
|
338
|
+
raise StreamlitAPIException(
|
339
|
+
"Selections are activated, but the provided chart spec does not "
|
340
|
+
"have any selections defined. To add selections to `st.altair_chart`, check out the documentation "
|
341
|
+
"[here](https://altair-viz.github.io/user_guide/interactions.html#selections-capturing-chart-interactions). "
|
342
|
+
"For adding selections to `st.vega_lite_chart`, take a look "
|
343
|
+
"at the specification [here](https://vega.github.io/vega-lite/docs/selection.html)."
|
344
|
+
)
|
345
|
+
|
346
|
+
if selection_mode is None:
|
347
|
+
# Activate all selection parameters:
|
348
|
+
return sorted(list(all_selection_params))
|
349
|
+
|
350
|
+
if isinstance(selection_mode, str):
|
351
|
+
# Convert single string to list:
|
352
|
+
selection_mode = [selection_mode]
|
353
|
+
|
354
|
+
# Check that all provided selection parameters are defined in the spec:
|
355
|
+
for selection_name in selection_mode:
|
356
|
+
if selection_name not in all_selection_params:
|
357
|
+
raise StreamlitAPIException(
|
358
|
+
f"Selection parameter '{selection_name}' is not defined in the chart spec. "
|
359
|
+
f"Available selection parameters are: {all_selection_params}."
|
360
|
+
)
|
361
|
+
return sorted(list(selection_mode))
|
362
|
+
|
363
|
+
|
218
364
|
def _reset_counter_pattern(prefix: str, vega_spec: str) -> str:
|
219
365
|
"""Altair uses a global counter for unnamed parameters and views.
|
220
366
|
We need to reset these counters on a spec-level to make the
|
@@ -459,11 +605,14 @@ class VegaChartsMixin:
|
|
459
605
|
width=width,
|
460
606
|
height=height,
|
461
607
|
)
|
462
|
-
return
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
608
|
+
return cast(
|
609
|
+
"DeltaGenerator",
|
610
|
+
self._altair_chart(
|
611
|
+
chart,
|
612
|
+
use_container_width=use_container_width,
|
613
|
+
theme="streamlit",
|
614
|
+
add_rows_metadata=add_rows_metadata,
|
615
|
+
),
|
467
616
|
)
|
468
617
|
|
469
618
|
@gather_metrics("area_chart")
|
@@ -618,11 +767,14 @@ class VegaChartsMixin:
|
|
618
767
|
width=width,
|
619
768
|
height=height,
|
620
769
|
)
|
621
|
-
return
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
770
|
+
return cast(
|
771
|
+
"DeltaGenerator",
|
772
|
+
self._altair_chart(
|
773
|
+
chart,
|
774
|
+
use_container_width=use_container_width,
|
775
|
+
theme="streamlit",
|
776
|
+
add_rows_metadata=add_rows_metadata,
|
777
|
+
),
|
626
778
|
)
|
627
779
|
|
628
780
|
@gather_metrics("bar_chart")
|
@@ -779,11 +931,14 @@ class VegaChartsMixin:
|
|
779
931
|
width=width,
|
780
932
|
height=height,
|
781
933
|
)
|
782
|
-
return
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
934
|
+
return cast(
|
935
|
+
"DeltaGenerator",
|
936
|
+
self._altair_chart(
|
937
|
+
chart,
|
938
|
+
use_container_width=use_container_width,
|
939
|
+
theme="streamlit",
|
940
|
+
add_rows_metadata=add_rows_metadata,
|
941
|
+
),
|
787
942
|
)
|
788
943
|
|
789
944
|
@gather_metrics("scatter_chart")
|
@@ -953,20 +1108,53 @@ class VegaChartsMixin:
|
|
953
1108
|
width=width,
|
954
1109
|
height=height,
|
955
1110
|
)
|
956
|
-
return
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
1111
|
+
return cast(
|
1112
|
+
"DeltaGenerator",
|
1113
|
+
self._altair_chart(
|
1114
|
+
chart,
|
1115
|
+
use_container_width=use_container_width,
|
1116
|
+
theme="streamlit",
|
1117
|
+
add_rows_metadata=add_rows_metadata,
|
1118
|
+
),
|
961
1119
|
)
|
962
1120
|
|
963
|
-
@
|
1121
|
+
@overload
|
964
1122
|
def altair_chart(
|
965
1123
|
self,
|
966
1124
|
altair_chart: alt.Chart,
|
1125
|
+
*,
|
967
1126
|
use_container_width: bool = False,
|
968
1127
|
theme: Literal["streamlit"] | None = "streamlit",
|
1128
|
+
key: Key | None = None,
|
1129
|
+
on_select: Literal["ignore"], # No default value here to make it work with mypy
|
1130
|
+
selection_mode: str | Iterable[str] | None = None,
|
969
1131
|
) -> DeltaGenerator:
|
1132
|
+
...
|
1133
|
+
|
1134
|
+
@overload
|
1135
|
+
def altair_chart(
|
1136
|
+
self,
|
1137
|
+
altair_chart: alt.Chart,
|
1138
|
+
*,
|
1139
|
+
use_container_width: bool = False,
|
1140
|
+
theme: Literal["streamlit"] | None = "streamlit",
|
1141
|
+
key: Key | None = None,
|
1142
|
+
on_select: Literal["rerun"] | WidgetCallback = "rerun",
|
1143
|
+
selection_mode: str | Iterable[str] | None = None,
|
1144
|
+
) -> VegaLiteState:
|
1145
|
+
...
|
1146
|
+
|
1147
|
+
@gather_metrics("altair_chart")
|
1148
|
+
def altair_chart(
|
1149
|
+
self,
|
1150
|
+
altair_chart: alt.Chart,
|
1151
|
+
*,
|
1152
|
+
use_container_width: bool = False,
|
1153
|
+
theme: Literal["streamlit"] | None = "streamlit",
|
1154
|
+
key: Key | None = None,
|
1155
|
+
on_select: Literal["rerun", "ignore"] | WidgetCallback = "ignore",
|
1156
|
+
selection_mode: str | Iterable[str] | None = None,
|
1157
|
+
) -> DeltaGenerator | VegaLiteState:
|
970
1158
|
"""Display a chart using the Altair library.
|
971
1159
|
|
972
1160
|
Parameters
|
@@ -982,6 +1170,20 @@ class VegaChartsMixin:
|
|
982
1170
|
The theme of the chart. Currently, we only support "streamlit" for the Streamlit
|
983
1171
|
defined design or None to fallback to the default behavior of the library.
|
984
1172
|
|
1173
|
+
key : str
|
1174
|
+
An optional string to use as the unique key for this element when used in combination
|
1175
|
+
with ```on_select```. If this is omitted, a key will be generated for the widget based
|
1176
|
+
on its content. Multiple widgets of the same type may not share the same key.
|
1177
|
+
|
1178
|
+
on_select : "ignore" or "rerun" or callable
|
1179
|
+
Controls the behavior in response to selection events on the charts. Can be one of:
|
1180
|
+
- "ignore" (default): Streamlit will not react to any selection events in the chart.
|
1181
|
+
- "rerun: Streamlit will rerun the app when the user selects data in the chart. In this case,
|
1182
|
+
```st.altair_chart``` will return the selection data as a dictionary.
|
1183
|
+
- callable: If a callable is provided, Streamlit will rerun and execute the callable as a
|
1184
|
+
callback function before the rest of the app. The selection data can be retrieved through
|
1185
|
+
session state by setting the key parameter.
|
1186
|
+
|
985
1187
|
Example
|
986
1188
|
-------
|
987
1189
|
|
@@ -1009,18 +1211,57 @@ class VegaChartsMixin:
|
|
1009
1211
|
|
1010
1212
|
"""
|
1011
1213
|
return self._altair_chart(
|
1012
|
-
altair_chart
|
1214
|
+
altair_chart=altair_chart,
|
1215
|
+
use_container_width=use_container_width,
|
1216
|
+
theme=theme,
|
1217
|
+
key=key,
|
1218
|
+
on_select=on_select,
|
1219
|
+
selection_mode=selection_mode,
|
1013
1220
|
)
|
1014
1221
|
|
1015
|
-
@
|
1222
|
+
@overload
|
1016
1223
|
def vega_lite_chart(
|
1017
1224
|
self,
|
1018
1225
|
data: Data = None,
|
1019
|
-
spec:
|
1226
|
+
spec: VegaLiteSpec | None = None,
|
1227
|
+
*,
|
1020
1228
|
use_container_width: bool = False,
|
1021
1229
|
theme: Literal["streamlit"] | None = "streamlit",
|
1230
|
+
key: Key | None = None,
|
1231
|
+
on_select: Literal["ignore"], # No default value here to make it work with mypy
|
1232
|
+
selection_mode: str | Iterable[str] | None = None,
|
1022
1233
|
**kwargs: Any,
|
1023
1234
|
) -> DeltaGenerator:
|
1235
|
+
...
|
1236
|
+
|
1237
|
+
@overload
|
1238
|
+
def vega_lite_chart(
|
1239
|
+
self,
|
1240
|
+
data: Data = None,
|
1241
|
+
spec: VegaLiteSpec | None = None,
|
1242
|
+
*,
|
1243
|
+
use_container_width: bool = False,
|
1244
|
+
theme: Literal["streamlit"] | None = "streamlit",
|
1245
|
+
key: Key | None = None,
|
1246
|
+
on_select: Literal["rerun"] | WidgetCallback = "rerun",
|
1247
|
+
selection_mode: str | Iterable[str] | None = None,
|
1248
|
+
**kwargs: Any,
|
1249
|
+
) -> VegaLiteState:
|
1250
|
+
...
|
1251
|
+
|
1252
|
+
@gather_metrics("vega_lite_chart")
|
1253
|
+
def vega_lite_chart(
|
1254
|
+
self,
|
1255
|
+
data: Data = None,
|
1256
|
+
spec: VegaLiteSpec | None = None,
|
1257
|
+
*,
|
1258
|
+
use_container_width: bool = False,
|
1259
|
+
theme: Literal["streamlit"] | None = "streamlit",
|
1260
|
+
key: Key | None = None,
|
1261
|
+
on_select: Literal["rerun", "ignore"] | WidgetCallback = "ignore",
|
1262
|
+
selection_mode: str | Iterable[str] | None = None,
|
1263
|
+
**kwargs: Any,
|
1264
|
+
) -> DeltaGenerator | VegaLiteState:
|
1024
1265
|
"""Display a chart using the Vega-Lite library.
|
1025
1266
|
|
1026
1267
|
Parameters
|
@@ -1042,6 +1283,20 @@ class VegaChartsMixin:
|
|
1042
1283
|
The theme of the chart. Currently, we only support "streamlit" for the Streamlit
|
1043
1284
|
defined design or None to fallback to the default behavior of the library.
|
1044
1285
|
|
1286
|
+
key : str
|
1287
|
+
An optional string to use as the unique key for this element when used in combination
|
1288
|
+
with ```on_select```. If this is omitted, a key will be generated for the widget based
|
1289
|
+
on its content. Multiple widgets of the same type may not share the same key.
|
1290
|
+
|
1291
|
+
on_select : "ignore" or "rerun" or callable
|
1292
|
+
Controls the behavior in response to selection events on the charts. Can be one of:
|
1293
|
+
- "ignore" (default): Streamlit will not react to any selection events in the chart.
|
1294
|
+
- "rerun: Streamlit will rerun the app when the user selects data in the chart. In this case,
|
1295
|
+
```st.vega_lite_chart``` will return the selection data as a dictionary.
|
1296
|
+
- callable: If a callable is provided, Streamlit will rerun and execute the callable as a
|
1297
|
+
callback function before the rest of the app. The selection data can be retrieved through
|
1298
|
+
session state by setting the key parameter.
|
1299
|
+
|
1045
1300
|
**kwargs : any
|
1046
1301
|
Same as spec, but as keywords.
|
1047
1302
|
|
@@ -1080,6 +1335,9 @@ class VegaChartsMixin:
|
|
1080
1335
|
spec=spec,
|
1081
1336
|
use_container_width=use_container_width,
|
1082
1337
|
theme=theme,
|
1338
|
+
key=key,
|
1339
|
+
on_select=on_select,
|
1340
|
+
selection_mode=selection_mode,
|
1083
1341
|
**kwargs,
|
1084
1342
|
)
|
1085
1343
|
|
@@ -1088,52 +1346,157 @@ class VegaChartsMixin:
|
|
1088
1346
|
altair_chart: alt.Chart,
|
1089
1347
|
use_container_width: bool = False,
|
1090
1348
|
theme: Literal["streamlit"] | None = "streamlit",
|
1349
|
+
key: Key | None = None,
|
1350
|
+
on_select: Literal["rerun", "ignore"] | WidgetCallback = "ignore",
|
1351
|
+
selection_mode: str | Iterable[str] | None = None,
|
1091
1352
|
add_rows_metadata: AddRowsMetadata | None = None,
|
1092
|
-
) -> DeltaGenerator:
|
1093
|
-
"""Internal method to enqueue a vega-lite chart element based on an Altair chart.
|
1353
|
+
) -> DeltaGenerator | VegaLiteState:
|
1354
|
+
"""Internal method to enqueue a vega-lite chart element based on an Altair chart.
|
1355
|
+
|
1356
|
+
See the `altair_chart` method docstring for more information.
|
1357
|
+
"""
|
1358
|
+
|
1359
|
+
if type_util.is_altair_version_less_than("5.0.0") and on_select != "ignore":
|
1360
|
+
raise StreamlitAPIException(
|
1361
|
+
"Streamlit does not support selections with Altair 4.x. Please upgrade to Version 5. "
|
1362
|
+
"If you would like to use Altair 4.x with selections, please upvote "
|
1363
|
+
"this [Github issue](https://github.com/streamlit/streamlit/issues/8516)."
|
1364
|
+
)
|
1365
|
+
|
1094
1366
|
vega_lite_spec = _convert_altair_to_vega_lite_spec(altair_chart)
|
1095
1367
|
return self._vega_lite_chart(
|
1096
1368
|
data=None, # The data is already part of the spec
|
1097
1369
|
spec=vega_lite_spec,
|
1098
1370
|
use_container_width=use_container_width,
|
1099
1371
|
theme=theme,
|
1372
|
+
key=key,
|
1373
|
+
on_select=on_select,
|
1374
|
+
selection_mode=selection_mode,
|
1100
1375
|
add_rows_metadata=add_rows_metadata,
|
1101
1376
|
)
|
1102
1377
|
|
1103
1378
|
def _vega_lite_chart(
|
1104
1379
|
self,
|
1105
1380
|
data: Data = None,
|
1106
|
-
spec:
|
1381
|
+
spec: VegaLiteSpec | None = None,
|
1107
1382
|
use_container_width: bool = False,
|
1108
1383
|
theme: Literal["streamlit"] | None = "streamlit",
|
1384
|
+
key: Key | None = None,
|
1385
|
+
on_select: Literal["rerun", "ignore"] | WidgetCallback = "ignore",
|
1386
|
+
selection_mode: str | Iterable[str] | None = None,
|
1109
1387
|
add_rows_metadata: AddRowsMetadata | None = None,
|
1110
1388
|
**kwargs: Any,
|
1111
|
-
) -> DeltaGenerator:
|
1112
|
-
"""Internal method to enqueue a vega-lite chart element based on a vega-lite spec.
|
1389
|
+
) -> DeltaGenerator | VegaLiteState:
|
1390
|
+
"""Internal method to enqueue a vega-lite chart element based on a vega-lite spec.
|
1391
|
+
|
1392
|
+
See the `vega_lite_chart` method docstring for more information.
|
1393
|
+
"""
|
1113
1394
|
|
1114
1395
|
if theme not in ["streamlit", None]:
|
1115
1396
|
raise StreamlitAPIException(
|
1116
1397
|
f'You set theme="{theme}" while Streamlit charts only support theme=”streamlit” or theme=None to fallback to the default library theme.'
|
1117
1398
|
)
|
1118
1399
|
|
1400
|
+
if on_select not in ["ignore", "rerun"] and not callable(on_select):
|
1401
|
+
raise StreamlitAPIException(
|
1402
|
+
f"You have passed {on_select} to `on_select`. But only 'ignore', 'rerun', or a callable is supported."
|
1403
|
+
)
|
1404
|
+
|
1405
|
+
key = to_key(key)
|
1406
|
+
is_selection_activated = on_select != "ignore"
|
1407
|
+
|
1408
|
+
if is_selection_activated:
|
1409
|
+
# Run some checks that are only relevant when selections are activated
|
1410
|
+
|
1411
|
+
# Import here to avoid circular imports
|
1412
|
+
from streamlit.elements.utils import (
|
1413
|
+
check_cache_replay_rules,
|
1414
|
+
check_callback_rules,
|
1415
|
+
check_session_state_rules,
|
1416
|
+
)
|
1417
|
+
|
1418
|
+
check_cache_replay_rules()
|
1419
|
+
if callable(on_select):
|
1420
|
+
check_callback_rules(self.dg, on_select)
|
1421
|
+
check_session_state_rules(default_value=None, key=key, writes_allowed=False)
|
1422
|
+
|
1119
1423
|
# Support passing data inside spec['datasets'] and spec['data'].
|
1120
1424
|
# (The data gets pulled out of the spec dict later on.)
|
1121
1425
|
if isinstance(data, dict) and spec is None:
|
1122
1426
|
spec = data
|
1123
1427
|
data = None
|
1124
1428
|
|
1125
|
-
|
1429
|
+
if spec is None:
|
1430
|
+
spec = {}
|
1431
|
+
|
1432
|
+
vega_lite_proto = ArrowVegaLiteChartProto()
|
1126
1433
|
|
1127
1434
|
spec = _prepare_vega_lite_spec(spec, use_container_width, **kwargs)
|
1128
|
-
_marshall_chart_data(
|
1435
|
+
_marshall_chart_data(vega_lite_proto, spec, data)
|
1129
1436
|
|
1130
1437
|
# Prevent the spec from changing across reruns:
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1438
|
+
vega_lite_proto.spec = _stabilize_vega_json_spec(json.dumps(spec))
|
1439
|
+
vega_lite_proto.use_container_width = use_container_width
|
1440
|
+
vega_lite_proto.theme = theme or ""
|
1441
|
+
|
1442
|
+
if is_selection_activated:
|
1443
|
+
# Import here to avoid circular imports
|
1444
|
+
from streamlit.elements.form import current_form_id
|
1445
|
+
|
1446
|
+
# Load the stabilized spec again as a dict:
|
1447
|
+
final_spec = json.loads(vega_lite_proto.spec)
|
1448
|
+
# Temporary limitation to disallow multi-view charts (compositions) with selections.
|
1449
|
+
_disallow_multi_view_charts(final_spec)
|
1450
|
+
|
1451
|
+
# Parse and check the specified selection modes
|
1452
|
+
parsed_selection_modes = _parse_selection_mode(final_spec, selection_mode)
|
1453
|
+
vega_lite_proto.selection_mode.extend(parsed_selection_modes)
|
1454
|
+
|
1455
|
+
vega_lite_proto.form_id = current_form_id(self.dg)
|
1456
|
+
|
1457
|
+
ctx = get_script_run_ctx()
|
1458
|
+
vega_lite_proto.id = compute_widget_id(
|
1459
|
+
"arrow_vega_lite_chart",
|
1460
|
+
user_key=key,
|
1461
|
+
key=key,
|
1462
|
+
vega_lite_spec=vega_lite_proto.spec,
|
1463
|
+
# The data is either in vega_lite_proto.data.data
|
1464
|
+
# or in a named dataset in vega_lite_proto.datasets
|
1465
|
+
vega_lite_data=vega_lite_proto.data.data,
|
1466
|
+
# Its enough to just use the names here since they are expected
|
1467
|
+
# to contain hashes based on the dataset data.
|
1468
|
+
named_datasets=[dataset.name for dataset in vega_lite_proto.datasets],
|
1469
|
+
theme=theme,
|
1470
|
+
use_container_width=use_container_width,
|
1471
|
+
selection_mode=parsed_selection_modes,
|
1472
|
+
form_id=vega_lite_proto.form_id,
|
1473
|
+
page=ctx.page_script_hash if ctx else None,
|
1474
|
+
)
|
1134
1475
|
|
1476
|
+
serde = VegaLiteStateSerde(parsed_selection_modes)
|
1477
|
+
|
1478
|
+
widget_state = register_widget(
|
1479
|
+
"vega_lite_chart",
|
1480
|
+
vega_lite_proto,
|
1481
|
+
user_key=key,
|
1482
|
+
on_change_handler=on_select if callable(on_select) else None,
|
1483
|
+
deserializer=serde.deserialize,
|
1484
|
+
serializer=serde.serialize,
|
1485
|
+
ctx=ctx,
|
1486
|
+
)
|
1487
|
+
|
1488
|
+
self.dg._enqueue(
|
1489
|
+
"arrow_vega_lite_chart",
|
1490
|
+
vega_lite_proto,
|
1491
|
+
add_rows_metadata=add_rows_metadata,
|
1492
|
+
)
|
1493
|
+
return cast(VegaLiteState, widget_state.value)
|
1494
|
+
# If its not used with selections activated, just return
|
1495
|
+
# the delta generator related to this element.
|
1135
1496
|
return self.dg._enqueue(
|
1136
|
-
"arrow_vega_lite_chart",
|
1497
|
+
"arrow_vega_lite_chart",
|
1498
|
+
vega_lite_proto,
|
1499
|
+
add_rows_metadata=add_rows_metadata,
|
1137
1500
|
)
|
1138
1501
|
|
1139
1502
|
@property
|
@@ -15,7 +15,7 @@ from streamlit.proto import Arrow_pb2 as streamlit_dot_proto_dot_Arrow__pb2
|
|
15
15
|
from streamlit.proto import ArrowNamedDataSet_pb2 as streamlit_dot_proto_dot_ArrowNamedDataSet__pb2
|
16
16
|
|
17
17
|
|
18
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(streamlit/proto/ArrowVegaLiteChart.proto\x1a\x1bstreamlit/proto/Arrow.proto\x1a\'streamlit/proto/ArrowNamedDataSet.proto\"\
|
18
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n(streamlit/proto/ArrowVegaLiteChart.proto\x1a\x1bstreamlit/proto/Arrow.proto\x1a\'streamlit/proto/ArrowNamedDataSet.proto\"\xc5\x01\n\x12\x41rrowVegaLiteChart\x12\x0c\n\x04spec\x18\x01 \x01(\t\x12\x14\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x06.Arrow\x12$\n\x08\x64\x61tasets\x18\x04 \x03(\x0b\x32\x12.ArrowNamedDataSet\x12\x1b\n\x13use_container_width\x18\x05 \x01(\x08\x12\r\n\x05theme\x18\x06 \x01(\t\x12\n\n\x02id\x18\x07 \x01(\t\x12\x16\n\x0eselection_mode\x18\x08 \x03(\t\x12\x0f\n\x07\x66orm_id\x18\t \x01(\tJ\x04\x08\x03\x10\x04\x42\x37\n\x1c\x63om.snowflake.apps.streamlitB\x17\x41rrowVegaLiteChartProtob\x06proto3')
|
19
19
|
|
20
20
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
21
21
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'streamlit.proto.ArrowVegaLiteChart_pb2', globals())
|
@@ -24,5 +24,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
24
24
|
DESCRIPTOR._options = None
|
25
25
|
DESCRIPTOR._serialized_options = b'\n\034com.snowflake.apps.streamlitB\027ArrowVegaLiteChartProto'
|
26
26
|
_ARROWVEGALITECHART._serialized_start=115
|
27
|
-
_ARROWVEGALITECHART._serialized_end=
|
27
|
+
_ARROWVEGALITECHART._serialized_end=312
|
28
28
|
# @@protoc_insertion_point(module_scope)
|