streamlit-nightly 1.33.1.dev20240426__py2.py3-none-any.whl → 1.33.1.dev20240429__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/elements/lib/event_utils.py +37 -0
- streamlit/elements/plotly_chart.py +266 -100
- streamlit/proto/PlotlyChart_pb2.py +7 -5
- streamlit/proto/PlotlyChart_pb2.pyi +61 -17
- streamlit/runtime/state/common.py +4 -2
- streamlit/runtime/state/widgets.py +1 -0
- streamlit/static/asset-manifest.json +15 -15
- streamlit/static/index.html +1 -1
- streamlit/static/static/css/{main.88b8fc58.css → main.3aaaea00.css} +1 -1
- streamlit/static/static/js/1168.fc5c673b.chunk.js +1 -0
- streamlit/static/static/js/{3092.d8143d1d.chunk.js → 3092.bc07c48b.chunk.js} +1 -1
- streamlit/static/static/js/{43.a48ac7b4.chunk.js → 43.c6749504.chunk.js} +1 -1
- streamlit/static/static/js/{4666.492dcf72.chunk.js → 4666.c4b22a63.chunk.js} +1 -1
- streamlit/static/static/js/{6013.8e80e091.chunk.js → 6013.64cd6d28.chunk.js} +1 -1
- streamlit/static/static/js/{6853.d999ac75.chunk.js → 6853.3cbd385e.chunk.js} +1 -1
- streamlit/static/static/js/{7602.6175e969.chunk.js → 7602.e8abc06b.chunk.js} +1 -1
- streamlit/static/static/js/{8427.88677af8.chunk.js → 8427.65ddaf36.chunk.js} +1 -1
- streamlit/static/static/js/{8477.e948c092.chunk.js → 8477.7419a0aa.chunk.js} +1 -1
- streamlit/static/static/js/{8492.f56c9d4c.chunk.js → 8492.3e609489.chunk.js} +1 -1
- streamlit/static/static/js/{8536.74dc408e.chunk.js → 8536.f13dff49.chunk.js} +1 -1
- streamlit/static/static/js/main.af77b7ba.js +2 -0
- {streamlit_nightly-1.33.1.dev20240426.dist-info → streamlit_nightly-1.33.1.dev20240429.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.33.1.dev20240426.dist-info → streamlit_nightly-1.33.1.dev20240429.dist-info}/RECORD +28 -27
- streamlit/static/static/js/1168.1d6408e6.chunk.js +0 -1
- streamlit/static/static/js/main.eccc579f.js +0 -2
- /streamlit/static/static/js/{main.eccc579f.js.LICENSE.txt → main.af77b7ba.js.LICENSE.txt} +0 -0
- {streamlit_nightly-1.33.1.dev20240426.data → streamlit_nightly-1.33.1.dev20240429.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.33.1.dev20240426.dist-info → streamlit_nightly-1.33.1.dev20240429.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.33.1.dev20240426.dist-info → streamlit_nightly-1.33.1.dev20240429.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.33.1.dev20240426.dist-info → streamlit_nightly-1.33.1.dev20240429.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2024)
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from typing import Any, Dict
|
16
|
+
|
17
|
+
|
18
|
+
class AttributeDictionary(Dict[Any, Any]):
|
19
|
+
"""
|
20
|
+
A dictionary subclass that supports attribute-style access.
|
21
|
+
|
22
|
+
This class extends the functionality of a standard dictionary to allow items to be accessed
|
23
|
+
via attribute-style dot notation in addition to the traditional key-based access. If a dictionary
|
24
|
+
item is accessed and is itself a dictionary, it is automatically wrapped in another `AttributeDictionary`,
|
25
|
+
enabling recursive attribute-style access.
|
26
|
+
"""
|
27
|
+
|
28
|
+
def __getattr__(self, key):
|
29
|
+
try:
|
30
|
+
item = self.__getitem__(key)
|
31
|
+
return AttributeDictionary(item) if isinstance(item, dict) else item
|
32
|
+
except KeyError as err:
|
33
|
+
raise AttributeError(
|
34
|
+
f"'{type(self).__name__}' object has no attribute '{key}'"
|
35
|
+
) from err
|
36
|
+
|
37
|
+
__setattr__ = dict.__setitem__
|
@@ -17,19 +17,37 @@
|
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
19
|
import json
|
20
|
-
import
|
21
|
-
from typing import
|
20
|
+
from dataclasses import dataclass
|
21
|
+
from typing import (
|
22
|
+
TYPE_CHECKING,
|
23
|
+
Any,
|
24
|
+
Dict,
|
25
|
+
Final,
|
26
|
+
Iterable,
|
27
|
+
List,
|
28
|
+
Literal,
|
29
|
+
TypedDict,
|
30
|
+
Union,
|
31
|
+
cast,
|
32
|
+
overload,
|
33
|
+
)
|
22
34
|
|
23
35
|
from typing_extensions import TypeAlias
|
24
36
|
|
25
37
|
from streamlit import type_util
|
38
|
+
from streamlit.deprecation_util import show_deprecation_warning
|
39
|
+
from streamlit.elements.form import current_form_id
|
40
|
+
from streamlit.elements.lib.event_utils import AttributeDictionary
|
26
41
|
from streamlit.elements.lib.streamlit_plotly_theme import (
|
27
42
|
configure_streamlit_plotly_theme,
|
28
43
|
)
|
29
44
|
from streamlit.errors import StreamlitAPIException
|
30
45
|
from streamlit.proto.PlotlyChart_pb2 import PlotlyChart as PlotlyChartProto
|
31
|
-
from streamlit.runtime.legacy_caching import caching
|
32
46
|
from streamlit.runtime.metrics_util import gather_metrics
|
47
|
+
from streamlit.runtime.scriptrunner import get_script_run_ctx
|
48
|
+
from streamlit.runtime.state import WidgetCallback, register_widget
|
49
|
+
from streamlit.runtime.state.common import compute_widget_id
|
50
|
+
from streamlit.type_util import Key, to_key
|
33
51
|
|
34
52
|
if TYPE_CHECKING:
|
35
53
|
import matplotlib
|
@@ -41,19 +59,6 @@ if TYPE_CHECKING:
|
|
41
59
|
# We need to configure the Plotly theme before any Plotly figures are created:
|
42
60
|
configure_streamlit_plotly_theme()
|
43
61
|
|
44
|
-
SharingMode: TypeAlias = Literal["streamlit", "private", "public", "secret"]
|
45
|
-
|
46
|
-
SHARING_MODES: set[SharingMode] = {
|
47
|
-
# This means the plot will be sent to the Streamlit app rather than to
|
48
|
-
# Plotly.
|
49
|
-
"streamlit",
|
50
|
-
# The three modes below are for plots that should be hosted in Plotly.
|
51
|
-
# These are the names Plotly uses for them.
|
52
|
-
"private",
|
53
|
-
"public",
|
54
|
-
"secret",
|
55
|
-
}
|
56
|
-
|
57
62
|
_AtomicFigureOrData: TypeAlias = Union[
|
58
63
|
"go.Figure",
|
59
64
|
"go.Data",
|
@@ -69,17 +74,154 @@ FigureOrData: TypeAlias = Union[
|
|
69
74
|
"matplotlib.figure.Figure",
|
70
75
|
]
|
71
76
|
|
77
|
+
SelectionMode: TypeAlias = Literal["lasso", "points", "box"]
|
78
|
+
_SELECTION_MODES: Final[set[SelectionMode]] = {"lasso", "points", "box"}
|
79
|
+
|
80
|
+
|
81
|
+
class PlotlySelectionState(TypedDict, total=False):
|
82
|
+
"""
|
83
|
+
A dictionary representing the current selection state of the plotly chart.
|
84
|
+
|
85
|
+
Attributes
|
86
|
+
----------
|
87
|
+
points : list[dict[str, Any]]
|
88
|
+
The selected data points in the chart, this also includes
|
89
|
+
the the data points selected by the box and lasso mode.
|
90
|
+
|
91
|
+
point_indices : list[int]
|
92
|
+
The numerical indices of all selected data points in the chart,
|
93
|
+
this also includes the indices of the points selected by the box
|
94
|
+
and lasso mode.
|
95
|
+
|
96
|
+
box : list[dict[str, Any]]
|
97
|
+
The metadata related to the box selection. This includes the
|
98
|
+
coordinates of the selected area.
|
99
|
+
|
100
|
+
lasso : list[dict[str, Any]]
|
101
|
+
The metadata related to the lasso selection. This includes the
|
102
|
+
coordinates of the selected area.
|
103
|
+
"""
|
104
|
+
|
105
|
+
points: list[dict[str, Any]]
|
106
|
+
point_indices: list[int]
|
107
|
+
box: list[dict[str, Any]]
|
108
|
+
lasso: list[dict[str, Any]]
|
109
|
+
|
110
|
+
|
111
|
+
class PlotlyState(TypedDict, total=False):
|
112
|
+
"""
|
113
|
+
A dictionary representing the current selection state of the plotly chart.
|
114
|
+
|
115
|
+
Attributes
|
116
|
+
----------
|
117
|
+
select : PlotlySelectionState
|
118
|
+
The state of the `on_select` event.
|
119
|
+
"""
|
120
|
+
|
121
|
+
select: PlotlySelectionState
|
122
|
+
|
123
|
+
|
124
|
+
@dataclass
|
125
|
+
class PlotlyChartSelectionSerde:
|
126
|
+
"""PlotlyChartSelectionSerde is used to serialize and deserialize the Plotly Chart selection state."""
|
127
|
+
|
128
|
+
def deserialize(self, ui_value: str | None, widget_id: str = "") -> PlotlyState:
|
129
|
+
empty_selection_state: PlotlyState = {
|
130
|
+
"select": {
|
131
|
+
"points": [],
|
132
|
+
"point_indices": [],
|
133
|
+
"box": [],
|
134
|
+
"lasso": [],
|
135
|
+
},
|
136
|
+
}
|
137
|
+
|
138
|
+
selection_state = (
|
139
|
+
empty_selection_state
|
140
|
+
if ui_value is None
|
141
|
+
else cast(PlotlyState, AttributeDictionary(json.loads(ui_value)))
|
142
|
+
)
|
143
|
+
|
144
|
+
if "select" not in selection_state:
|
145
|
+
selection_state = empty_selection_state
|
146
|
+
|
147
|
+
return cast(PlotlyState, AttributeDictionary(selection_state))
|
148
|
+
|
149
|
+
def serialize(self, selection_state: PlotlyState) -> str:
|
150
|
+
return json.dumps(selection_state, default=str)
|
151
|
+
|
152
|
+
|
153
|
+
def parse_selection_mode(
|
154
|
+
selection_mode: SelectionMode | Iterable[SelectionMode],
|
155
|
+
) -> set[PlotlyChartProto.SelectionMode.ValueType]:
|
156
|
+
"""Parse and check the user provided selection modes."""
|
157
|
+
if isinstance(selection_mode, str):
|
158
|
+
# Only a single selection mode was passed
|
159
|
+
selection_mode_set = {selection_mode}
|
160
|
+
else:
|
161
|
+
# Multiple selection modes were passed
|
162
|
+
selection_mode_set = set(selection_mode)
|
163
|
+
|
164
|
+
if not selection_mode_set.issubset(_SELECTION_MODES):
|
165
|
+
raise StreamlitAPIException(
|
166
|
+
f"Invalid selection mode: {selection_mode}. "
|
167
|
+
f"Valid options are: {_SELECTION_MODES}"
|
168
|
+
)
|
169
|
+
|
170
|
+
parsed_selection_modes = []
|
171
|
+
for selection_mode in selection_mode_set:
|
172
|
+
if selection_mode == "points":
|
173
|
+
parsed_selection_modes.append(PlotlyChartProto.SelectionMode.POINTS)
|
174
|
+
elif selection_mode == "lasso":
|
175
|
+
parsed_selection_modes.append(PlotlyChartProto.SelectionMode.LASSO)
|
176
|
+
elif selection_mode == "box":
|
177
|
+
parsed_selection_modes.append(PlotlyChartProto.SelectionMode.BOX)
|
178
|
+
return set(parsed_selection_modes)
|
179
|
+
|
72
180
|
|
73
181
|
class PlotlyMixin:
|
74
|
-
@
|
182
|
+
@overload
|
75
183
|
def plotly_chart(
|
76
184
|
self,
|
77
185
|
figure_or_data: FigureOrData,
|
78
186
|
use_container_width: bool = False,
|
79
|
-
|
187
|
+
*,
|
80
188
|
theme: Literal["streamlit"] | None = "streamlit",
|
189
|
+
key: Key | None = None,
|
190
|
+
on_select: Literal["ignore"], # No default value here to make it work with mypy
|
191
|
+
selection_mode: SelectionMode
|
192
|
+
| Iterable[SelectionMode] = ("points", "box", "lasso"),
|
81
193
|
**kwargs: Any,
|
82
194
|
) -> DeltaGenerator:
|
195
|
+
...
|
196
|
+
|
197
|
+
@overload
|
198
|
+
def plotly_chart(
|
199
|
+
self,
|
200
|
+
figure_or_data: FigureOrData,
|
201
|
+
use_container_width: bool = False,
|
202
|
+
*,
|
203
|
+
theme: Literal["streamlit"] | None = "streamlit",
|
204
|
+
key: Key | None = None,
|
205
|
+
on_select: Literal["rerun"] | WidgetCallback = "rerun",
|
206
|
+
selection_mode: SelectionMode
|
207
|
+
| Iterable[SelectionMode] = ("points", "box", "lasso"),
|
208
|
+
**kwargs: Any,
|
209
|
+
) -> PlotlyState:
|
210
|
+
...
|
211
|
+
|
212
|
+
@gather_metrics("plotly_chart")
|
213
|
+
def plotly_chart(
|
214
|
+
self,
|
215
|
+
figure_or_data: FigureOrData,
|
216
|
+
use_container_width: bool = False,
|
217
|
+
*,
|
218
|
+
theme: Literal["streamlit"] | None = "streamlit",
|
219
|
+
key: Key | None = None,
|
220
|
+
on_select: Literal["rerun", "ignore"] | WidgetCallback = "ignore",
|
221
|
+
selection_mode: SelectionMode
|
222
|
+
| Iterable[SelectionMode] = ("points", "box", "lasso"),
|
223
|
+
**kwargs: Any,
|
224
|
+
) -> DeltaGenerator | PlotlyState:
|
83
225
|
"""Display an interactive Plotly chart.
|
84
226
|
|
85
227
|
Plotly is a charting library for Python. The arguments to this function
|
@@ -100,16 +242,33 @@ class PlotlyMixin:
|
|
100
242
|
If True, set the chart width to the column width. This takes
|
101
243
|
precedence over the figure's native `width` value.
|
102
244
|
|
103
|
-
sharing : "streamlit", "private", "secret", or "public"
|
104
|
-
Use "streamlit" to insert the plot and all its dependencies
|
105
|
-
directly in the Streamlit app using plotly's offline mode (default).
|
106
|
-
Use any other sharing mode to send the chart to Plotly chart studio, which
|
107
|
-
requires an account. See https://plot.ly/python/chart-studio/ for more information.
|
108
|
-
|
109
245
|
theme : "streamlit" or None
|
110
246
|
The theme of the chart. Currently, we only support "streamlit" for the Streamlit
|
111
247
|
defined design or None to fallback to the default behavior of the library.
|
112
248
|
|
249
|
+
key : str
|
250
|
+
An optional string to use as the unique key for this element when used in combination
|
251
|
+
with ```on_select```. If this is omitted, a key will be generated for the widget based
|
252
|
+
on its content. Multiple widgets of the same type may not share the same key.
|
253
|
+
|
254
|
+
on_select : "ignore" or "rerun" or callable
|
255
|
+
Controls the behavior in response to selection events on the charts. Can be one of:
|
256
|
+
- "ignore" (default): Streamlit will not react to any selection events in the chart.
|
257
|
+
- "rerun: Streamlit will rerun the app when the user selects data in the chart. In this case,
|
258
|
+
```st.plotly_chart``` will return the selection data as a dictionary.
|
259
|
+
- callable: If a callable is provided, Streamlit will rerun and execute the callable as a
|
260
|
+
callback function before the rest of the app. The selection data can be retrieved through
|
261
|
+
session state by setting the key parameter.
|
262
|
+
|
263
|
+
selection_mode : "points", "box", "lasso" or an iterable of these
|
264
|
+
The selection mode of the table. Can be one of:
|
265
|
+
- "points": The chart will allow selections based on individual data points.
|
266
|
+
- "box": The chart will allow selections based on rectangular areas.
|
267
|
+
- "lasso": The chart will allow selections based on freeform areas.
|
268
|
+
- An iterable of the above options: The chart will allow selections based on the modes specified.
|
269
|
+
|
270
|
+
All selections modes are activated by default.
|
271
|
+
|
113
272
|
**kwargs
|
114
273
|
Any argument accepted by Plotly's `plot()` function.
|
115
274
|
|
@@ -144,104 +303,111 @@ class PlotlyMixin:
|
|
144
303
|
height: 400px
|
145
304
|
|
146
305
|
"""
|
306
|
+
import plotly.io
|
307
|
+
import plotly.tools
|
308
|
+
|
147
309
|
# NOTE: "figure_or_data" is the name used in Plotly's .plot() method
|
148
310
|
# for their main parameter. I don't like the name, but it's best to
|
149
311
|
# keep it in sync with what Plotly calls it.
|
150
312
|
|
151
|
-
|
152
|
-
|
313
|
+
if "sharing" in kwargs:
|
314
|
+
show_deprecation_warning(
|
315
|
+
"The `sharing` parameter has been deprecated and will be removed in a future release. "
|
316
|
+
"Plotly charts will always be rendered using Streamlit's offline mode."
|
317
|
+
)
|
318
|
+
|
319
|
+
if theme not in ["streamlit", None]:
|
153
320
|
raise StreamlitAPIException(
|
154
321
|
f'You set theme="{theme}" while Streamlit charts only support theme=”streamlit” or theme=None to fallback to the default library theme.'
|
155
322
|
)
|
156
|
-
marshall(
|
157
|
-
plotly_chart_proto,
|
158
|
-
figure_or_data,
|
159
|
-
use_container_width,
|
160
|
-
sharing,
|
161
|
-
theme,
|
162
|
-
**kwargs,
|
163
|
-
)
|
164
|
-
return self.dg._enqueue("plotly_chart", plotly_chart_proto)
|
165
|
-
|
166
|
-
@property
|
167
|
-
def dg(self) -> DeltaGenerator:
|
168
|
-
"""Get our DeltaGenerator."""
|
169
|
-
return cast("DeltaGenerator", self)
|
170
|
-
|
171
|
-
|
172
|
-
def marshall(
|
173
|
-
proto: PlotlyChartProto,
|
174
|
-
figure_or_data: FigureOrData,
|
175
|
-
use_container_width: bool,
|
176
|
-
sharing: SharingMode,
|
177
|
-
theme: Literal["streamlit"] | None,
|
178
|
-
**kwargs: Any,
|
179
|
-
) -> None:
|
180
|
-
"""Marshall a proto with a Plotly spec.
|
181
|
-
|
182
|
-
See DeltaGenerator.plotly_chart for docs.
|
183
|
-
"""
|
184
|
-
# NOTE: "figure_or_data" is the name used in Plotly's .plot() method
|
185
|
-
# for their main parameter. I don't like the name, but its best to keep
|
186
|
-
# it in sync with what Plotly calls it.
|
187
323
|
|
188
|
-
|
324
|
+
if on_select not in ["ignore", "rerun"] and not callable(on_select):
|
325
|
+
raise StreamlitAPIException(
|
326
|
+
f"You have passed {on_select} to `on_select`. But only 'ignore', 'rerun', or a callable is supported."
|
327
|
+
)
|
189
328
|
|
190
|
-
|
191
|
-
|
329
|
+
key = to_key(key)
|
330
|
+
is_selection_activated = on_select != "ignore"
|
192
331
|
|
193
|
-
|
194
|
-
|
195
|
-
figure_or_data, validate_figure=True
|
196
|
-
)
|
332
|
+
if is_selection_activated:
|
333
|
+
# Run some checks that are only relevant when selections are activated
|
197
334
|
|
198
|
-
|
199
|
-
|
335
|
+
# Import here to avoid circular imports
|
336
|
+
from streamlit.elements.utils import (
|
337
|
+
check_cache_replay_rules,
|
338
|
+
check_callback_rules,
|
339
|
+
check_session_state_rules,
|
340
|
+
)
|
200
341
|
|
201
|
-
|
342
|
+
check_cache_replay_rules()
|
343
|
+
if callable(on_select):
|
344
|
+
check_callback_rules(self.dg, on_select)
|
345
|
+
check_session_state_rules(default_value=None, key=key, writes_allowed=False)
|
346
|
+
|
347
|
+
if type_util.is_type(figure_or_data, "matplotlib.figure.Figure"):
|
348
|
+
# Convert matplotlib figure to plotly figure:
|
349
|
+
figure = plotly.tools.mpl_to_plotly(figure_or_data)
|
350
|
+
else:
|
351
|
+
figure = plotly.tools.return_figure_from_figure_or_data(
|
352
|
+
figure_or_data, validate_figure=True
|
353
|
+
)
|
202
354
|
|
203
|
-
|
204
|
-
|
355
|
+
plotly_chart_proto = PlotlyChartProto()
|
356
|
+
plotly_chart_proto.use_container_width = use_container_width
|
357
|
+
plotly_chart_proto.theme = theme or ""
|
358
|
+
plotly_chart_proto.form_id = current_form_id(self.dg)
|
205
359
|
|
206
360
|
config = dict(kwargs.get("config", {}))
|
207
361
|
# Copy over some kwargs to config dict. Plotly does the same in plot().
|
208
362
|
config.setdefault("showLink", kwargs.get("show_link", False))
|
209
363
|
config.setdefault("linkText", kwargs.get("link_text", False))
|
210
364
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
365
|
+
plotly_chart_proto.spec = plotly.io.to_json(figure, validate=False)
|
366
|
+
plotly_chart_proto.config = json.dumps(config)
|
367
|
+
|
368
|
+
ctx = get_script_run_ctx()
|
369
|
+
|
370
|
+
# We are computing the widget id for all plotly uses
|
371
|
+
# to also allow non-widget Plotly charts to keep their state
|
372
|
+
# when the frontend component gets unmounted and remounted.
|
373
|
+
plotly_chart_proto.id = compute_widget_id(
|
374
|
+
"plotly_chart",
|
375
|
+
user_key=key,
|
376
|
+
key=key,
|
377
|
+
plotly_spec=plotly_chart_proto.spec,
|
378
|
+
plotly_config=plotly_chart_proto.config,
|
379
|
+
selection_mode=selection_mode,
|
380
|
+
is_selection_activated=is_selection_activated,
|
381
|
+
theme=theme,
|
382
|
+
form_id=plotly_chart_proto.form_id,
|
383
|
+
use_container_width=use_container_width,
|
384
|
+
page=ctx.page_script_hash if ctx else None,
|
217
385
|
)
|
218
|
-
proto.url = _get_embed_url(url)
|
219
|
-
proto.theme = theme or ""
|
220
386
|
|
387
|
+
if is_selection_activated:
|
388
|
+
# Selections are activated, treat plotly chart as a widget:
|
389
|
+
plotly_chart_proto.selection_mode.extend(
|
390
|
+
parse_selection_mode(selection_mode)
|
391
|
+
)
|
221
392
|
|
222
|
-
|
223
|
-
def _plot_to_url_or_load_cached_url(*args: Any, **kwargs: Any) -> go.Figure:
|
224
|
-
"""Call plotly.plot wrapped in st.cache.
|
225
|
-
|
226
|
-
This is so we don't unnecessarily upload data to Plotly's SASS if nothing
|
227
|
-
changed since the previous upload.
|
228
|
-
"""
|
229
|
-
try:
|
230
|
-
# Plotly 4 changed its main package.
|
231
|
-
import chart_studio.plotly as ply
|
232
|
-
except ImportError:
|
233
|
-
import plotly.plotly as ply
|
234
|
-
|
235
|
-
return ply.plot(*args, **kwargs)
|
236
|
-
|
393
|
+
serde = PlotlyChartSelectionSerde()
|
237
394
|
|
238
|
-
|
239
|
-
|
395
|
+
widget_state = register_widget(
|
396
|
+
"plotly_chart",
|
397
|
+
plotly_chart_proto,
|
398
|
+
user_key=key,
|
399
|
+
on_change_handler=on_select if callable(on_select) else None,
|
400
|
+
deserializer=serde.deserialize,
|
401
|
+
serializer=serde.serialize,
|
402
|
+
ctx=ctx,
|
403
|
+
)
|
240
404
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
parsed_embed_url = parsed_url._replace(path=parsed_url.path + ".embed")
|
405
|
+
self.dg._enqueue("plotly_chart", plotly_chart_proto)
|
406
|
+
return cast(PlotlyState, widget_state.value)
|
407
|
+
else:
|
408
|
+
return self.dg._enqueue("plotly_chart", plotly_chart_proto)
|
246
409
|
|
247
|
-
|
410
|
+
@property
|
411
|
+
def dg(self) -> DeltaGenerator:
|
412
|
+
"""Get our DeltaGenerator."""
|
413
|
+
return cast("DeltaGenerator", self)
|
@@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default()
|
|
13
13
|
|
14
14
|
|
15
15
|
|
16
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!streamlit/proto/PlotlyChart.proto\"
|
16
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!streamlit/proto/PlotlyChart.proto\"\x98\x02\n\x0bPlotlyChart\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\x32\n\x0eselection_mode\x18\x08 \x03(\x0e\x32\x1a.PlotlyChart.SelectionMode\x12\x0f\n\x07\x66orm_id\x18\t \x01(\t\x12\x0c\n\x04spec\x18\n \x01(\t\x12\x0e\n\x06\x63onfig\x18\x0b \x01(\t\x12\r\n\x03url\x18\x01 \x01(\tH\x00\x12\x19\n\x06\x66igure\x18\x02 \x01(\x0b\x32\x07.FigureH\x00\"/\n\rSelectionMode\x12\n\n\x06POINTS\x10\x00\x12\x07\n\x03\x42OX\x10\x01\x12\t\n\x05LASSO\x10\x02\x42\x07\n\x05\x63hartJ\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05\"&\n\x06\x46igure\x12\x0c\n\x04spec\x18\x01 \x01(\t\x12\x0e\n\x06\x63onfig\x18\x02 \x01(\tB0\n\x1c\x63om.snowflake.apps.streamlitB\x10PlotlyChartProtob\x06proto3')
|
17
17
|
|
18
18
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
19
19
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'streamlit.proto.PlotlyChart_pb2', globals())
|
@@ -21,8 +21,10 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
21
21
|
|
22
22
|
DESCRIPTOR._options = None
|
23
23
|
DESCRIPTOR._serialized_options = b'\n\034com.snowflake.apps.streamlitB\020PlotlyChartProto'
|
24
|
-
_PLOTLYCHART._serialized_start=
|
25
|
-
_PLOTLYCHART._serialized_end=
|
26
|
-
|
27
|
-
|
24
|
+
_PLOTLYCHART._serialized_start=38
|
25
|
+
_PLOTLYCHART._serialized_end=318
|
26
|
+
_PLOTLYCHART_SELECTIONMODE._serialized_start=250
|
27
|
+
_PLOTLYCHART_SELECTIONMODE._serialized_end=297
|
28
|
+
_FIGURE._serialized_start=320
|
29
|
+
_FIGURE._serialized_end=358
|
28
30
|
# @@protoc_insertion_point(module_scope)
|
@@ -17,11 +17,15 @@ See the License for the specific language governing permissions and
|
|
17
17
|
limitations under the License.
|
18
18
|
"""
|
19
19
|
import builtins
|
20
|
+
import collections.abc
|
20
21
|
import google.protobuf.descriptor
|
22
|
+
import google.protobuf.internal.containers
|
23
|
+
import google.protobuf.internal.enum_type_wrapper
|
21
24
|
import google.protobuf.message
|
22
25
|
import sys
|
26
|
+
import typing
|
23
27
|
|
24
|
-
if sys.version_info >= (3,
|
28
|
+
if sys.version_info >= (3, 10):
|
25
29
|
import typing as typing_extensions
|
26
30
|
else:
|
27
31
|
import typing_extensions
|
@@ -31,46 +35,86 @@ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
|
31
35
|
class PlotlyChart(google.protobuf.message.Message):
|
32
36
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
33
37
|
|
34
|
-
|
35
|
-
|
38
|
+
class _SelectionMode:
|
39
|
+
ValueType = typing.NewType("ValueType", builtins.int)
|
40
|
+
V: typing_extensions.TypeAlias = ValueType
|
41
|
+
|
42
|
+
class _SelectionModeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[PlotlyChart._SelectionMode.ValueType], builtins.type): # noqa: F821
|
43
|
+
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
44
|
+
POINTS: PlotlyChart._SelectionMode.ValueType # 0
|
45
|
+
"""Point selection mode"""
|
46
|
+
BOX: PlotlyChart._SelectionMode.ValueType # 1
|
47
|
+
"""Box selection mode"""
|
48
|
+
LASSO: PlotlyChart._SelectionMode.ValueType # 2
|
49
|
+
"""Lasso selection mode"""
|
50
|
+
|
51
|
+
class SelectionMode(_SelectionMode, metaclass=_SelectionModeEnumTypeWrapper):
|
52
|
+
"""Available selection modes:"""
|
53
|
+
|
54
|
+
POINTS: PlotlyChart.SelectionMode.ValueType # 0
|
55
|
+
"""Point selection mode"""
|
56
|
+
BOX: PlotlyChart.SelectionMode.ValueType # 1
|
57
|
+
"""Box selection mode"""
|
58
|
+
LASSO: PlotlyChart.SelectionMode.ValueType # 2
|
59
|
+
"""Lasso selection mode"""
|
60
|
+
|
36
61
|
USE_CONTAINER_WIDTH_FIELD_NUMBER: builtins.int
|
37
62
|
THEME_FIELD_NUMBER: builtins.int
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
here the plot's dict spec as JSON.
|
46
|
-
"""
|
63
|
+
ID_FIELD_NUMBER: builtins.int
|
64
|
+
SELECTION_MODE_FIELD_NUMBER: builtins.int
|
65
|
+
FORM_ID_FIELD_NUMBER: builtins.int
|
66
|
+
SPEC_FIELD_NUMBER: builtins.int
|
67
|
+
CONFIG_FIELD_NUMBER: builtins.int
|
68
|
+
URL_FIELD_NUMBER: builtins.int
|
69
|
+
FIGURE_FIELD_NUMBER: builtins.int
|
47
70
|
use_container_width: builtins.bool
|
48
71
|
"""If True, will overwrite the chart width spec to fit to container."""
|
49
72
|
theme: builtins.str
|
50
73
|
"""override the properties with a theme. Currently, only "streamlit" or None are accepted."""
|
74
|
+
id: builtins.str
|
75
|
+
"""The unique element ID of this chart."""
|
76
|
+
@property
|
77
|
+
def selection_mode(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[global___PlotlyChart.SelectionMode.ValueType]:
|
78
|
+
"""Activate selections types on the chart."""
|
79
|
+
form_id: builtins.str
|
80
|
+
"""Form ID, filled if selections are activated."""
|
81
|
+
spec: builtins.str
|
82
|
+
"""JSON-serialized dict containing keys from the set {data, frames, layout}."""
|
83
|
+
config: builtins.str
|
84
|
+
"""JSON-serialized dict with Plotly's config object."""
|
85
|
+
url: builtins.str
|
86
|
+
"""DEPRECATED and unused."""
|
87
|
+
@property
|
88
|
+
def figure(self) -> global___Figure:
|
89
|
+
"""DEPRECATED and unused."""
|
51
90
|
def __init__(
|
52
91
|
self,
|
53
92
|
*,
|
54
|
-
url: builtins.str = ...,
|
55
|
-
figure: global___Figure | None = ...,
|
56
93
|
use_container_width: builtins.bool = ...,
|
57
94
|
theme: builtins.str = ...,
|
95
|
+
id: builtins.str = ...,
|
96
|
+
selection_mode: collections.abc.Iterable[global___PlotlyChart.SelectionMode.ValueType] | None = ...,
|
97
|
+
form_id: builtins.str = ...,
|
98
|
+
spec: builtins.str = ...,
|
99
|
+
config: builtins.str = ...,
|
100
|
+
url: builtins.str = ...,
|
101
|
+
figure: global___Figure | None = ...,
|
58
102
|
) -> None: ...
|
59
103
|
def HasField(self, field_name: typing_extensions.Literal["chart", b"chart", "figure", b"figure", "url", b"url"]) -> builtins.bool: ...
|
60
|
-
def ClearField(self, field_name: typing_extensions.Literal["chart", b"chart", "figure", b"figure", "theme", b"theme", "url", b"url", "use_container_width", b"use_container_width"]) -> None: ...
|
104
|
+
def ClearField(self, field_name: typing_extensions.Literal["chart", b"chart", "config", b"config", "figure", b"figure", "form_id", b"form_id", "id", b"id", "selection_mode", b"selection_mode", "spec", b"spec", "theme", b"theme", "url", b"url", "use_container_width", b"use_container_width"]) -> None: ...
|
61
105
|
def WhichOneof(self, oneof_group: typing_extensions.Literal["chart", b"chart"]) -> typing_extensions.Literal["url", "figure"] | None: ...
|
62
106
|
|
63
107
|
global___PlotlyChart = PlotlyChart
|
64
108
|
|
65
109
|
class Figure(google.protobuf.message.Message):
|
110
|
+
"""DEPRECATED and unused."""
|
111
|
+
|
66
112
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
67
113
|
|
68
114
|
SPEC_FIELD_NUMBER: builtins.int
|
69
115
|
CONFIG_FIELD_NUMBER: builtins.int
|
70
116
|
spec: builtins.str
|
71
|
-
"""JSON-serialized dict containing keys from the set {data, frames, layout}."""
|
72
117
|
config: builtins.str
|
73
|
-
"""JSON-serialized dict with Plotly's config object."""
|
74
118
|
def __init__(
|
75
119
|
self,
|
76
120
|
*,
|
@@ -26,7 +26,7 @@ from typing import (
|
|
26
26
|
Dict,
|
27
27
|
Final,
|
28
28
|
Generic,
|
29
|
-
|
29
|
+
Iterable,
|
30
30
|
Tuple,
|
31
31
|
TypeVar,
|
32
32
|
Union,
|
@@ -49,6 +49,7 @@ from streamlit.proto.DownloadButton_pb2 import DownloadButton
|
|
49
49
|
from streamlit.proto.FileUploader_pb2 import FileUploader
|
50
50
|
from streamlit.proto.MultiSelect_pb2 import MultiSelect
|
51
51
|
from streamlit.proto.NumberInput_pb2 import NumberInput
|
52
|
+
from streamlit.proto.PlotlyChart_pb2 import PlotlyChart
|
52
53
|
from streamlit.proto.Radio_pb2 import Radio
|
53
54
|
from streamlit.proto.Selectbox_pb2 import Selectbox
|
54
55
|
from streamlit.proto.Slider_pb2 import Slider
|
@@ -85,6 +86,7 @@ WidgetProto: TypeAlias = Union[
|
|
85
86
|
TextArea,
|
86
87
|
TextInput,
|
87
88
|
TimeInput,
|
89
|
+
PlotlyChart,
|
88
90
|
]
|
89
91
|
|
90
92
|
GENERATED_WIDGET_ID_PREFIX: Final = "$$WIDGET_ID"
|
@@ -180,7 +182,7 @@ SAFE_VALUES = Union[
|
|
180
182
|
def compute_widget_id(
|
181
183
|
element_type: str,
|
182
184
|
user_key: str | None = None,
|
183
|
-
**kwargs: SAFE_VALUES |
|
185
|
+
**kwargs: SAFE_VALUES | Iterable[SAFE_VALUES],
|
184
186
|
) -> str:
|
185
187
|
"""Compute the widget id for the given widget. This id is stable: a given
|
186
188
|
set of inputs to this function will always produce the same widget id output.
|