streamlit 1.48.1__py3-none-any.whl → 1.49.1__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/__init__.py +3 -10
- streamlit/commands/logo.py +4 -3
- streamlit/commands/navigation.py +1 -1
- streamlit/commands/page_config.py +4 -1
- streamlit/components/v1/custom_component.py +2 -2
- streamlit/config.py +82 -1
- streamlit/connections/snowflake_connection.py +3 -1
- streamlit/delta_generator.py +3 -0
- streamlit/elements/arrow.py +155 -70
- streamlit/elements/bokeh_chart.py +13 -3
- streamlit/elements/deck_gl_json_chart.py +0 -1
- streamlit/elements/dialog_decorator.py +7 -59
- streamlit/elements/form.py +10 -1
- streamlit/elements/graphviz_chart.py +57 -6
- streamlit/elements/heading.py +17 -16
- streamlit/elements/image.py +64 -37
- streamlit/elements/layouts.py +2 -2
- streamlit/elements/lib/built_in_chart_utils.py +2 -5
- streamlit/elements/lib/column_config_utils.py +18 -4
- streamlit/elements/lib/column_types.py +75 -30
- streamlit/elements/lib/dialog.py +3 -3
- streamlit/elements/lib/image_utils.py +19 -11
- streamlit/elements/lib/layout_utils.py +19 -6
- streamlit/elements/lib/utils.py +20 -41
- streamlit/elements/markdown.py +7 -6
- streamlit/elements/media.py +6 -13
- streamlit/elements/metric.py +78 -1
- streamlit/elements/pdf.py +192 -0
- streamlit/elements/plotly_chart.py +3 -2
- streamlit/elements/pyplot.py +53 -11
- streamlit/elements/toast.py +81 -5
- streamlit/elements/vega_charts.py +3 -8
- streamlit/elements/widgets/audio_input.py +0 -1
- streamlit/elements/widgets/button.py +0 -4
- streamlit/elements/widgets/button_group.py +5 -4
- streamlit/elements/widgets/camera_input.py +0 -1
- streamlit/elements/widgets/chat.py +11 -13
- streamlit/elements/widgets/checkbox.py +0 -1
- streamlit/elements/widgets/color_picker.py +0 -1
- streamlit/elements/widgets/data_editor.py +142 -62
- streamlit/elements/widgets/file_uploader.py +74 -37
- streamlit/elements/widgets/multiselect.py +0 -1
- streamlit/elements/widgets/number_input.py +0 -1
- streamlit/elements/widgets/radio.py +0 -1
- streamlit/elements/widgets/select_slider.py +0 -1
- streamlit/elements/widgets/selectbox.py +0 -1
- streamlit/elements/widgets/slider.py +0 -1
- streamlit/elements/widgets/text_widgets.py +0 -2
- streamlit/elements/widgets/time_widgets.py +0 -2
- streamlit/errors.py +11 -0
- streamlit/material_icon_names.py +1 -1
- streamlit/proto/Arrow_pb2.py +14 -8
- streamlit/proto/Arrow_pb2.pyi +11 -3
- streamlit/proto/Block_pb2.py +16 -16
- streamlit/proto/Block_pb2.pyi +2 -0
- streamlit/proto/ChatInput_pb2.py +3 -3
- streamlit/proto/ChatInput_pb2.pyi +2 -0
- streamlit/proto/FileUploader_pb2.py +2 -2
- streamlit/proto/FileUploader_pb2.pyi +5 -1
- streamlit/proto/GraphVizChart_pb2.py +4 -2
- streamlit/proto/GraphVizChart_pb2.pyi +1 -1
- streamlit/proto/Image_pb2.py +4 -2
- streamlit/proto/Image_pb2.pyi +1 -10
- streamlit/proto/Metric_pb2.py +8 -6
- streamlit/proto/Metric_pb2.pyi +34 -10
- streamlit/proto/Toast_pb2.py +2 -2
- streamlit/proto/Toast_pb2.pyi +10 -1
- streamlit/runtime/caching/__init__.py +14 -2
- streamlit/runtime/caching/cache_data_api.py +0 -17
- streamlit/runtime/caching/cache_resource_api.py +0 -16
- streamlit/runtime/caching/cached_message_replay.py +8 -20
- streamlit/runtime/caching/hashing.py +31 -1
- streamlit/runtime/credentials.py +4 -4
- streamlit/runtime/fragment.py +0 -42
- streamlit/runtime/websocket_session_manager.py +1 -1
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +223 -251
- streamlit/static/static/css/{index.CJVRHjQZ.css → index.C8X8rNzw.css} +1 -1
- streamlit/static/static/css/index.COe1010n.css +1 -0
- streamlit/static/static/js/{ErrorOutline.esm.DjObtx4K.js → ErrorOutline.esm.DcGrhbBP.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.Bz9nxNC5.js → FileDownload.esm.DgBvV6Pq.js} +1 -1
- streamlit/static/static/js/FileHelper.M6AAaeuA.js +5 -0
- streamlit/static/static/js/FormClearHelper.DHh1GFzm.js +1 -0
- streamlit/static/static/js/{Hooks.DEoLCfOE.js → Hooks.DGu1od_L.js} +1 -1
- streamlit/static/static/js/InputInstructions.z6sVgyYt.js +1 -0
- streamlit/static/static/js/Particles.DDVT-6Qc.js +1 -0
- streamlit/static/static/js/ProgressBar.BEY0cXXV.js +2 -0
- streamlit/static/static/js/Toolbar.DSnK1fUh.js +1 -0
- streamlit/static/static/js/{base-input.BmvSaPd2.js → base-input.CK3UVGp1.js} +4 -4
- streamlit/static/static/js/{checkbox.Cgxgc0et.js → checkbox.D8W881TL.js} +2 -2
- streamlit/static/static/js/createSuper.B6W-Dh9S.js +1 -0
- streamlit/static/static/js/data-grid-overlay-editor.DRTHOydk.js +1 -0
- streamlit/static/static/js/{downloader.M6jQeNDf.js → downloader.DiKpuU_S.js} +1 -1
- streamlit/static/static/js/es6.B8zRNPZ-.js +2 -0
- streamlit/static/static/js/iframeResizer.contentWindow.DIewJmmh.js +1 -0
- streamlit/static/static/js/index.452cqrrL.js +1 -0
- streamlit/static/static/js/index.4eF4NxG2.js +1 -0
- streamlit/static/static/js/index.B6U8LQo3.js +1 -0
- streamlit/static/static/js/index.B9mjBcgE.js +1 -0
- streamlit/static/static/js/index.BXYmrqnf.js +1 -0
- streamlit/static/static/js/index.B_8AnktO.js +1 -0
- streamlit/static/static/js/index.Bl7zGQSh.js +7 -0
- streamlit/static/static/js/index.BnEpvLEz.js +1 -0
- streamlit/static/static/js/{index.D1EayrNh.js → index.BnJIOYn9.js} +2 -2
- streamlit/static/static/js/index.Bte_9Lyq.js +1 -0
- streamlit/static/static/js/index.C1HcTl5K.js +1 -0
- streamlit/static/static/js/index.C7fRKRs4.js +1 -0
- streamlit/static/static/js/index.C7lSmSOP.js +1 -0
- streamlit/static/static/js/index.CD8HuT3N.js +976 -0
- streamlit/static/static/js/index.CP5TD2z1.js +1 -0
- streamlit/static/static/js/index.C_tmcx4B.js +1 -0
- streamlit/static/static/js/index.CcJf6BCU.js +3858 -0
- streamlit/static/static/js/{index.CbdWnLqS.js → index.CejBxbg1.js} +3 -3
- streamlit/static/static/js/index.Ch7MBCx0.js +5367 -0
- streamlit/static/static/js/index.CjXWwH-y.js +1 -0
- streamlit/static/static/js/index.CvYYtxD_.js +1 -0
- streamlit/static/static/js/index.D2-atlaQ.js +3 -0
- streamlit/static/static/js/index.D3K5nOu9.js +197 -0
- streamlit/static/static/js/index.D5naqx-J.js +1 -0
- streamlit/static/static/js/index.Dk4C7X3i.js +1 -0
- streamlit/static/static/js/index.DkKT3LUI.js +1 -0
- streamlit/static/static/js/index.DtYN2x4k.js +1 -0
- streamlit/static/static/js/index.MTPPBDHk.js +2 -0
- streamlit/static/static/js/{index.Cqa4gqqN.js → index.Ts_0SdB9.js} +1 -1
- streamlit/static/static/js/{index.CgZDfhN4.js → index.cnnXF7xQ.js} +2 -2
- streamlit/static/static/js/index.ho6NIXGl.js +1 -0
- streamlit/static/static/js/index.pqW9AMJD.js +3 -0
- streamlit/static/static/js/{index.D1jHqUJq.js → index.qhs54UAB.js} +1 -1
- streamlit/static/static/js/{index.tsvTLdio.js → index.urHgTgMQ.js} +9 -9
- streamlit/static/static/js/index.wzkv_11M.js +1 -0
- streamlit/static/static/js/index.yF5AncHY.js +1 -0
- streamlit/static/static/js/{index.BXDq9dj4.js → index.zecpGxtj.js} +1 -1
- streamlit/static/static/js/{input.DZd6EQlV.js → input.nzVJphXi.js} +2 -2
- streamlit/static/static/js/{memory.ptkfuI71.js → memory.CjCgTQz3.js} +1 -1
- streamlit/static/static/js/number-overlay-editor.DaRFzZEO.js +9 -0
- streamlit/static/static/js/{possibleConstructorReturn.Bd4ImlQ9.js → possibleConstructorReturn.DgiPnZ9N.js} +1 -1
- streamlit/static/static/js/{sandbox.DsH8LuID.js → sandbox.mithfq7Z.js} +1 -1
- streamlit/static/static/js/{timepicker.QVekV78C.js → timepicker.Dbl5KFh6.js} +4 -4
- streamlit/static/static/js/{toConsumableArray.BJvaP8gb.js → toConsumableArray.D-Dx88BQ.js} +3 -3
- streamlit/static/static/js/uniqueId.Bh26R_3S.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.DB3vMS9V.js → useBasicWidgetState.DeK-QJpD.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.CBkGkaRt.js → useTextInputAutoExpand.4iAdLWD-.js} +2 -2
- streamlit/static/static/js/useUpdateUiValue.CmT7_nJN.js +1 -0
- streamlit/static/static/js/withFullScreenWrapper.DLp1ENGm.js +1 -0
- streamlit/static/static/media/MaterialSymbols-Rounded.CBxVaFdk.woff2 +0 -0
- streamlit/user_info.py +3 -1
- streamlit/web/server/browser_websocket_handler.py +15 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.1.dist-info}/METADATA +4 -2
- {streamlit-1.48.1.dist-info → streamlit-1.49.1.dist-info}/RECORD +153 -156
- streamlit/static/static/css/index.CQt5TjGB.css +0 -1
- streamlit/static/static/js/FileHelper.BrQvUXVD.js +0 -5
- streamlit/static/static/js/FormClearHelper.DF4gFAOO.js +0 -1
- streamlit/static/static/js/InputInstructions.D8zoMog9.js +0 -1
- streamlit/static/static/js/Particles.CCFySwdL.js +0 -1
- streamlit/static/static/js/ProgressBar.COK9j1l0.js +0 -2
- streamlit/static/static/js/Toolbar.Dt4jIKlY.js +0 -1
- streamlit/static/static/js/createSuper.siQeagI2.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.Ct51iCb_.js +0 -1
- streamlit/static/static/js/es6.CMaUdEZ5.js +0 -2
- streamlit/static/static/js/iframeResizer.contentWindow.C33BryyP.js +0 -1
- streamlit/static/static/js/index.8GJD0eeD.js +0 -1
- streamlit/static/static/js/index.8QEYHMQD.js +0 -1
- streamlit/static/static/js/index.Ay41Wnu9.js +0 -1
- streamlit/static/static/js/index.BLiKiJ7_.js +0 -1
- streamlit/static/static/js/index.BT78cJmU.js +0 -1
- streamlit/static/static/js/index.BdGvnhlM.js +0 -1
- streamlit/static/static/js/index.BfasrT0d.js +0 -1
- streamlit/static/static/js/index.CCdtFMFG.js +0 -1
- streamlit/static/static/js/index.CFRGZDz1.js +0 -1
- streamlit/static/static/js/index.CFSFYiPA.js +0 -5366
- streamlit/static/static/js/index.CeiIiXap.js +0 -1
- streamlit/static/static/js/index.CzX2xpyc.js +0 -1
- streamlit/static/static/js/index.D1ErX5go.js +0 -2
- streamlit/static/static/js/index.D5gweoL5.js +0 -7
- streamlit/static/static/js/index.DByVKZgq.js +0 -1
- streamlit/static/static/js/index.DEND45D1.js +0 -3
- streamlit/static/static/js/index.DKN5MVff.js +0 -781
- streamlit/static/static/js/index.DfoxW1gP.js +0 -3855
- streamlit/static/static/js/index.Dtf1Ac0x.js +0 -1
- streamlit/static/static/js/index.DxrLhpeO.js +0 -1
- streamlit/static/static/js/index.J7o-_HIh.js +0 -1
- streamlit/static/static/js/index.LU8juINp.js +0 -197
- streamlit/static/static/js/index.L_N2iylt.js +0 -1
- streamlit/static/static/js/index.PZUX2kRz.js +0 -3
- streamlit/static/static/js/index.ROjU6K0k.js +0 -1
- streamlit/static/static/js/index.WSNLkF94.js +0 -1
- streamlit/static/static/js/index.X5W3gJLn.js +0 -1
- streamlit/static/static/js/index.k9LYqfSL.js +0 -1
- streamlit/static/static/js/index.pnHtHv_c.js +0 -203
- streamlit/static/static/js/index.tPUXqsfW.js +0 -1
- streamlit/static/static/js/mergeWith.GRNk8iwv.js +0 -1
- streamlit/static/static/js/number-overlay-editor.DXS2qb1U.js +0 -9
- streamlit/static/static/js/threshold.DjX0wlsa.js +0 -1
- streamlit/static/static/js/timer.CAwTRJ_g.js +0 -1
- streamlit/static/static/js/uniqueId.D_5M8Dgf.js +0 -1
- streamlit/static/static/js/useUpdateUiValue.C7ZKpLQK.js +0 -1
- streamlit/static/static/js/value.CgPGBV_l.js +0 -1
- streamlit/static/static/js/withFullScreenWrapper.C-gXt0Rl.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.DsbC8sYI.woff2 +0 -0
- {streamlit-1.48.1.data → streamlit-1.49.1.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.1.dist-info}/WHEEL +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.1.dist-info}/entry_points.txt +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.1.dist-info}/top_level.txt +0 -0
streamlit/elements/media.py
CHANGED
|
@@ -23,7 +23,6 @@ from typing import TYPE_CHECKING, Final, Union, cast
|
|
|
23
23
|
from typing_extensions import TypeAlias
|
|
24
24
|
|
|
25
25
|
from streamlit import runtime, type_util, url_util
|
|
26
|
-
from streamlit.elements.lib.form_utils import current_form_id
|
|
27
26
|
from streamlit.elements.lib.layout_utils import WidthWithoutContent, validate_width
|
|
28
27
|
from streamlit.elements.lib.subtitle_utils import process_subtitle_data
|
|
29
28
|
from streamlit.elements.lib.utils import compute_and_register_element_id
|
|
@@ -210,6 +209,7 @@ class MediaMixin:
|
|
|
210
209
|
)
|
|
211
210
|
coordinates = self.dg._get_delta_path_str()
|
|
212
211
|
marshall_audio(
|
|
212
|
+
self.dg,
|
|
213
213
|
coordinates,
|
|
214
214
|
audio_proto,
|
|
215
215
|
data,
|
|
@@ -219,7 +219,6 @@ class MediaMixin:
|
|
|
219
219
|
end_time,
|
|
220
220
|
loop,
|
|
221
221
|
autoplay,
|
|
222
|
-
form_id=current_form_id(self.dg),
|
|
223
222
|
width=width,
|
|
224
223
|
)
|
|
225
224
|
return self.dg._enqueue("audio", audio_proto)
|
|
@@ -389,6 +388,7 @@ class MediaMixin:
|
|
|
389
388
|
video_proto = VideoProto()
|
|
390
389
|
coordinates = self.dg._get_delta_path_str()
|
|
391
390
|
marshall_video(
|
|
391
|
+
self.dg,
|
|
392
392
|
coordinates,
|
|
393
393
|
video_proto,
|
|
394
394
|
data,
|
|
@@ -399,7 +399,6 @@ class MediaMixin:
|
|
|
399
399
|
loop,
|
|
400
400
|
autoplay,
|
|
401
401
|
muted,
|
|
402
|
-
form_id=current_form_id(self.dg),
|
|
403
402
|
width=width,
|
|
404
403
|
)
|
|
405
404
|
return self.dg._enqueue("video", video_proto)
|
|
@@ -500,6 +499,7 @@ def _marshall_av_media(
|
|
|
500
499
|
|
|
501
500
|
|
|
502
501
|
def marshall_video(
|
|
502
|
+
dg: DeltaGenerator,
|
|
503
503
|
coordinates: str,
|
|
504
504
|
proto: VideoProto,
|
|
505
505
|
data: MediaData,
|
|
@@ -510,7 +510,6 @@ def marshall_video(
|
|
|
510
510
|
loop: bool = False,
|
|
511
511
|
autoplay: bool = False,
|
|
512
512
|
muted: bool = False,
|
|
513
|
-
form_id: str | None = None,
|
|
514
513
|
width: WidthWithoutContent = "stretch",
|
|
515
514
|
) -> None:
|
|
516
515
|
"""Marshalls a video proto, using url processors as needed.
|
|
@@ -555,9 +554,6 @@ def marshall_video(
|
|
|
555
554
|
muted: bool
|
|
556
555
|
Whether the video should play with the audio silenced. This can be used to
|
|
557
556
|
enable autoplay without user interaction. Defaults to False.
|
|
558
|
-
form_id: str | None
|
|
559
|
-
The ID of the form that this element is placed in. Provide None if
|
|
560
|
-
the element is not placed in a form.
|
|
561
557
|
width: int or "stretch"
|
|
562
558
|
The width of the video player. This can be one of the following:
|
|
563
559
|
- An int: The width in pixels, e.g. 200 for a width of 200 pixels.
|
|
@@ -643,7 +639,7 @@ def marshall_video(
|
|
|
643
639
|
"video",
|
|
644
640
|
# video does not yet allow setting a user-defined key
|
|
645
641
|
user_key=None,
|
|
646
|
-
|
|
642
|
+
dg=dg,
|
|
647
643
|
url=proto.url,
|
|
648
644
|
mimetype=mimetype,
|
|
649
645
|
start_time=start_time,
|
|
@@ -763,6 +759,7 @@ def _maybe_convert_to_wav_bytes(data: MediaData, sample_rate: int | None) -> Med
|
|
|
763
759
|
|
|
764
760
|
|
|
765
761
|
def marshall_audio(
|
|
762
|
+
dg: DeltaGenerator,
|
|
766
763
|
coordinates: str,
|
|
767
764
|
proto: AudioProto,
|
|
768
765
|
data: MediaData,
|
|
@@ -772,7 +769,6 @@ def marshall_audio(
|
|
|
772
769
|
end_time: int | None = None,
|
|
773
770
|
loop: bool = False,
|
|
774
771
|
autoplay: bool = False,
|
|
775
|
-
form_id: str | None = None,
|
|
776
772
|
width: WidthWithoutContent = "stretch",
|
|
777
773
|
) -> None:
|
|
778
774
|
"""Marshalls an audio proto, using data and url processors as needed.
|
|
@@ -800,9 +796,6 @@ def marshall_audio(
|
|
|
800
796
|
autoplay : bool
|
|
801
797
|
Whether the audio should start playing automatically.
|
|
802
798
|
Browsers will not autoplay audio files if the user has not interacted with the page yet.
|
|
803
|
-
form_id: str | None
|
|
804
|
-
The ID of the form that this element is placed in. Provide None if
|
|
805
|
-
the element is not placed in a form.
|
|
806
799
|
width: int or "stretch"
|
|
807
800
|
The width of the audio player. This can be one of the following:
|
|
808
801
|
- An int: The width in pixels, e.g. 200 for a width of 200 pixels.
|
|
@@ -838,7 +831,7 @@ def marshall_audio(
|
|
|
838
831
|
proto.id = compute_and_register_element_id(
|
|
839
832
|
"audio",
|
|
840
833
|
user_key=None,
|
|
841
|
-
|
|
834
|
+
dg=dg,
|
|
842
835
|
url=proto.url,
|
|
843
836
|
mimetype=mimetype,
|
|
844
837
|
start_time=start_time,
|
streamlit/elements/metric.py
CHANGED
|
@@ -20,6 +20,7 @@ from typing import TYPE_CHECKING, Any, Literal, Union, cast
|
|
|
20
20
|
|
|
21
21
|
from typing_extensions import TypeAlias
|
|
22
22
|
|
|
23
|
+
from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
|
|
23
24
|
from streamlit.elements.lib.layout_utils import (
|
|
24
25
|
Height,
|
|
25
26
|
LayoutConfig,
|
|
@@ -62,11 +63,14 @@ class MetricMixin:
|
|
|
62
63
|
value: Value,
|
|
63
64
|
delta: Delta = None,
|
|
64
65
|
delta_color: DeltaColor = "normal",
|
|
66
|
+
*,
|
|
65
67
|
help: str | None = None,
|
|
66
68
|
label_visibility: LabelVisibility = "visible",
|
|
67
69
|
border: bool = False,
|
|
68
70
|
width: Width = "stretch",
|
|
69
71
|
height: Height = "content",
|
|
72
|
+
chart_data: OptionSequence[Any] | None = None,
|
|
73
|
+
chart_type: Literal["line", "bar", "area"] = "line",
|
|
70
74
|
) -> DeltaGenerator:
|
|
71
75
|
r"""Display a metric in big bold font, with an optional indicator of how the metric changed.
|
|
72
76
|
|
|
@@ -156,6 +160,22 @@ class MetricMixin:
|
|
|
156
160
|
the parent container, the width of the element matches the width
|
|
157
161
|
of the parent container.
|
|
158
162
|
|
|
163
|
+
chart_data : Iterable or None
|
|
164
|
+
A sequence of numeric values to display as a sparkline chart. If
|
|
165
|
+
this is ``None`` (default), no chart is displayed. The sequence can
|
|
166
|
+
be anything supported by ``st.dataframe``, including a ``list`` or
|
|
167
|
+
``set``. If the sequence is dataframe-like, the first column will
|
|
168
|
+
be used. Each value will be cast to ``float`` internally by
|
|
169
|
+
default.
|
|
170
|
+
|
|
171
|
+
chart_type : "line", "bar", or "area"
|
|
172
|
+
The type of sparkline chart to display. This can be one of the
|
|
173
|
+
following:
|
|
174
|
+
|
|
175
|
+
- ``"line"`` (default): A simple sparkline.
|
|
176
|
+
- ``"area"``: A sparkline with area shading.
|
|
177
|
+
- ``"bar"``: A bar chart.
|
|
178
|
+
|
|
159
179
|
Examples
|
|
160
180
|
--------
|
|
161
181
|
**Example 1: Show a metric**
|
|
@@ -192,7 +212,10 @@ class MetricMixin:
|
|
|
192
212
|
>>> st.metric(label="Gas price", value=4, delta=-0.5, delta_color="inverse")
|
|
193
213
|
>>>
|
|
194
214
|
>>> st.metric(
|
|
195
|
-
... label="Active developers",
|
|
215
|
+
... label="Active developers",
|
|
216
|
+
... value=123,
|
|
217
|
+
... delta=123,
|
|
218
|
+
... delta_color="off",
|
|
196
219
|
... )
|
|
197
220
|
|
|
198
221
|
.. output::
|
|
@@ -218,6 +241,33 @@ class MetricMixin:
|
|
|
218
241
|
https://doc-metric-example4.streamlit.app/
|
|
219
242
|
height: 350px
|
|
220
243
|
|
|
244
|
+
**Example 5: Show sparklines**
|
|
245
|
+
|
|
246
|
+
To show trends over time, add sparklines.
|
|
247
|
+
|
|
248
|
+
>>> import streamlit as st
|
|
249
|
+
>>> from numpy.random import default_rng as rng
|
|
250
|
+
>>>
|
|
251
|
+
>>> changes = list(rng(4).standard_normal(20))
|
|
252
|
+
>>> data = [sum(changes[:i]) for i in range(20)]
|
|
253
|
+
>>> delta = round(data[-1], 2)
|
|
254
|
+
>>>
|
|
255
|
+
>>> row = st.container(horizontal=True)
|
|
256
|
+
>>> with row:
|
|
257
|
+
>>> st.metric(
|
|
258
|
+
... "Line", 10, delta, chart_data=data, chart_type="line", border=True
|
|
259
|
+
... )
|
|
260
|
+
>>> st.metric(
|
|
261
|
+
... "Area", 10, delta, chart_data=data, chart_type="area", border=True
|
|
262
|
+
... )
|
|
263
|
+
>>> st.metric(
|
|
264
|
+
... "Bar", 10, delta, chart_data=data, chart_type="bar", border=True
|
|
265
|
+
... )
|
|
266
|
+
|
|
267
|
+
.. output::
|
|
268
|
+
https://doc-metric-example5.streamlit.app/
|
|
269
|
+
height: 300px
|
|
270
|
+
|
|
221
271
|
"""
|
|
222
272
|
maybe_raise_label_warnings(label, label_visibility)
|
|
223
273
|
|
|
@@ -238,6 +288,22 @@ class MetricMixin:
|
|
|
238
288
|
label_visibility
|
|
239
289
|
)
|
|
240
290
|
|
|
291
|
+
if chart_data is not None:
|
|
292
|
+
prepared_data: list[float] = []
|
|
293
|
+
for val in convert_anything_to_list(chart_data):
|
|
294
|
+
try:
|
|
295
|
+
prepared_data.append(float(val))
|
|
296
|
+
except Exception as ex: # noqa: PERF203
|
|
297
|
+
raise StreamlitAPIException(
|
|
298
|
+
"Only numeric values are supported for chart data sequence. The "
|
|
299
|
+
f"value '{val}' is of type {type(val)} and "
|
|
300
|
+
"cannot be converted to float."
|
|
301
|
+
) from ex
|
|
302
|
+
if len(prepared_data) > 0:
|
|
303
|
+
metric_proto.chart_data.extend(prepared_data)
|
|
304
|
+
|
|
305
|
+
metric_proto.chart_type = _parse_chart_type(chart_type)
|
|
306
|
+
|
|
241
307
|
validate_height(height, allow_content=True)
|
|
242
308
|
validate_width(width, allow_content=True)
|
|
243
309
|
layout_config = LayoutConfig(width=width, height=height)
|
|
@@ -249,6 +315,17 @@ class MetricMixin:
|
|
|
249
315
|
return cast("DeltaGenerator", self)
|
|
250
316
|
|
|
251
317
|
|
|
318
|
+
def _parse_chart_type(
|
|
319
|
+
chart_type: Literal["line", "bar", "area"],
|
|
320
|
+
) -> MetricProto.ChartType.ValueType:
|
|
321
|
+
if chart_type == "bar":
|
|
322
|
+
return MetricProto.ChartType.BAR
|
|
323
|
+
if chart_type == "area":
|
|
324
|
+
return MetricProto.ChartType.AREA
|
|
325
|
+
# Use line as default chart:
|
|
326
|
+
return MetricProto.ChartType.LINE
|
|
327
|
+
|
|
328
|
+
|
|
252
329
|
def _parse_label(label: str) -> str:
|
|
253
330
|
if not isinstance(label, str):
|
|
254
331
|
raise TypeError(
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
|
|
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 __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import io
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import TYPE_CHECKING, Any, Union, cast
|
|
20
|
+
|
|
21
|
+
from typing_extensions import TypeAlias
|
|
22
|
+
|
|
23
|
+
from streamlit import url_util
|
|
24
|
+
from streamlit.elements.lib.layout_utils import validate_height
|
|
25
|
+
from streamlit.errors import StreamlitAPIException
|
|
26
|
+
from streamlit.runtime.metrics_util import gather_metrics
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from streamlit.delta_generator import DeltaGenerator
|
|
30
|
+
from streamlit.elements.lib.layout_utils import HeightWithoutContent
|
|
31
|
+
|
|
32
|
+
PdfData: TypeAlias = Union[str, Path, bytes, io.BytesIO]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _get_pdf_component() -> Any | None:
|
|
36
|
+
"""Get the PDF custom component if available.
|
|
37
|
+
|
|
38
|
+
Returns
|
|
39
|
+
-------
|
|
40
|
+
Any | None
|
|
41
|
+
The pdf_viewer function if the streamlit-pdf component is available,
|
|
42
|
+
None otherwise.
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
import streamlit_pdf # type: ignore
|
|
46
|
+
|
|
47
|
+
return streamlit_pdf.pdf_viewer
|
|
48
|
+
except ImportError:
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class PdfMixin:
|
|
53
|
+
@gather_metrics("pdf")
|
|
54
|
+
def pdf(
|
|
55
|
+
self,
|
|
56
|
+
data: PdfData,
|
|
57
|
+
*,
|
|
58
|
+
height: HeightWithoutContent = 500,
|
|
59
|
+
key: str | None = None,
|
|
60
|
+
) -> DeltaGenerator:
|
|
61
|
+
"""Display a PDF viewer.
|
|
62
|
+
|
|
63
|
+
.. Important::
|
|
64
|
+
|
|
65
|
+
You must install |streamlit-pdf|_ to use this command. You can
|
|
66
|
+
install it as an extra with Streamlit:
|
|
67
|
+
|
|
68
|
+
.. code-block:: shell
|
|
69
|
+
|
|
70
|
+
pip install streamlit[pdf]
|
|
71
|
+
|
|
72
|
+
.. |streamlit-pdf| replace:: ``streamlit-pdf``
|
|
73
|
+
.. _streamlit-pdf: https://github.com/streamlit/streamlit-pdf
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
data : str, Path, BytesIO, or bytes
|
|
78
|
+
The PDF file to show. This can be one of the following:
|
|
79
|
+
|
|
80
|
+
- A URL (string) for a hosted PDF file.
|
|
81
|
+
- A path to a local PDF file. If you use a relative path, it must
|
|
82
|
+
be relative to the current working directory.
|
|
83
|
+
- A file-like object. For example, this can be an ``UploadedFile``
|
|
84
|
+
from ``st.file_uploader``, or this can be a local file opened
|
|
85
|
+
with ``open()``.
|
|
86
|
+
- Raw bytes data.
|
|
87
|
+
|
|
88
|
+
height : int or "stretch"
|
|
89
|
+
The height of the PDF viewer. This can be one of the following:
|
|
90
|
+
|
|
91
|
+
- An integer specifying the height in pixels: The viewer has a
|
|
92
|
+
fixed height. If the content is larger than the specified
|
|
93
|
+
height, scrolling is enabled. This is ``500`` by default.
|
|
94
|
+
- ``"stretch"``: The height of the viewer matches the height of
|
|
95
|
+
its content or the height of the parent container, whichever is
|
|
96
|
+
larger. If the viewer is not in a parent container, the height
|
|
97
|
+
of the viewer matches the height of its content.
|
|
98
|
+
|
|
99
|
+
Example
|
|
100
|
+
-------
|
|
101
|
+
>>> st.pdf("https://example.com/sample.pdf")
|
|
102
|
+
>>> st.pdf("https://example.com/sample.pdf", height=600)
|
|
103
|
+
"""
|
|
104
|
+
# Validate data parameter early
|
|
105
|
+
if data is None:
|
|
106
|
+
raise StreamlitAPIException(
|
|
107
|
+
"The PDF data cannot be None. Please provide a valid PDF file path, URL, "
|
|
108
|
+
"bytes data, or file-like object."
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Check if custom PDF component is available first
|
|
112
|
+
pdf_component = _get_pdf_component()
|
|
113
|
+
if pdf_component is None:
|
|
114
|
+
return self._show_pdf_warning()
|
|
115
|
+
|
|
116
|
+
return self._call_pdf_component(pdf_component, data, height, key)
|
|
117
|
+
|
|
118
|
+
def _call_pdf_component(
|
|
119
|
+
self,
|
|
120
|
+
pdf_component: Any,
|
|
121
|
+
data: PdfData,
|
|
122
|
+
height: HeightWithoutContent,
|
|
123
|
+
key: str | None,
|
|
124
|
+
) -> DeltaGenerator:
|
|
125
|
+
"""Call the custom PDF component with the provided data."""
|
|
126
|
+
# Validate height parameter after confirming component is available
|
|
127
|
+
validate_height(height, allow_content=False)
|
|
128
|
+
|
|
129
|
+
# Convert data to the format expected by pdf_viewer component
|
|
130
|
+
file_param: str | bytes
|
|
131
|
+
|
|
132
|
+
if isinstance(data, (str, Path)):
|
|
133
|
+
data_str = str(data).strip() # Strip whitespace from URLs
|
|
134
|
+
if url_util.is_url(data_str, allowed_schemas=("http", "https")):
|
|
135
|
+
# It's a URL - pass directly
|
|
136
|
+
file_param = data_str
|
|
137
|
+
else:
|
|
138
|
+
# It's a local file path - read the content as bytes for security
|
|
139
|
+
try:
|
|
140
|
+
with open(data_str, "rb") as file:
|
|
141
|
+
file_param = file.read()
|
|
142
|
+
except (FileNotFoundError, PermissionError) as e:
|
|
143
|
+
raise StreamlitAPIException(
|
|
144
|
+
f"Unable to read file '{data_str}': {e}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
elif isinstance(data, bytes):
|
|
148
|
+
# Pass bytes directly - the component will handle uploading to media storage
|
|
149
|
+
file_param = data
|
|
150
|
+
elif hasattr(data, "read") and hasattr(data, "getvalue"):
|
|
151
|
+
# Handle BytesIO and similar
|
|
152
|
+
file_param = data.getvalue()
|
|
153
|
+
elif hasattr(data, "read"):
|
|
154
|
+
# Handle other file-like objects
|
|
155
|
+
file_param = data.read()
|
|
156
|
+
else:
|
|
157
|
+
# Provide a more helpful error message
|
|
158
|
+
raise StreamlitAPIException(
|
|
159
|
+
f"Unsupported data type for PDF: {type(data).__name__}. "
|
|
160
|
+
f"Please provide a file path (str or Path), URL (str), bytes data, "
|
|
161
|
+
f"or file-like object (such as BytesIO or UploadedFile)."
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Convert to component-compatible format
|
|
165
|
+
if height == "stretch":
|
|
166
|
+
# For stretch, we need to pass a special value the component understands
|
|
167
|
+
# This maintains compatibility with the component while using standard layout
|
|
168
|
+
component_height = "stretch"
|
|
169
|
+
else:
|
|
170
|
+
component_height = str(height)
|
|
171
|
+
|
|
172
|
+
result = pdf_component(
|
|
173
|
+
file=file_param,
|
|
174
|
+
height=component_height,
|
|
175
|
+
key=key,
|
|
176
|
+
)
|
|
177
|
+
return cast("DeltaGenerator", result)
|
|
178
|
+
|
|
179
|
+
def _show_pdf_warning(self) -> DeltaGenerator:
|
|
180
|
+
"""Raise an exception that the PDF component is not available."""
|
|
181
|
+
raise StreamlitAPIException(
|
|
182
|
+
"The PDF viewer requires the `streamlit-pdf` component to be installed.\n\n"
|
|
183
|
+
"Please run `pip install streamlit[pdf]` to install it.\n\n"
|
|
184
|
+
"For more information, see the Streamlit PDF documentation at "
|
|
185
|
+
"https://docs.streamlit.io/develop/api-reference/media/st.pdf."
|
|
186
|
+
# TODO: Update this URL when docs are updated
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def dg(self) -> DeltaGenerator:
|
|
191
|
+
"""Get our DeltaGenerator."""
|
|
192
|
+
return cast("DeltaGenerator", self)
|
|
@@ -333,7 +333,9 @@ class PlotlyMixin:
|
|
|
333
333
|
can install all charting dependencies (except Bokeh) as an extra
|
|
334
334
|
with Streamlit:
|
|
335
335
|
|
|
336
|
-
|
|
336
|
+
.. code-block:: shell
|
|
337
|
+
|
|
338
|
+
pip install streamlit[charts]
|
|
337
339
|
|
|
338
340
|
Parameters
|
|
339
341
|
----------
|
|
@@ -556,7 +558,6 @@ class PlotlyMixin:
|
|
|
556
558
|
plotly_chart_proto.id = compute_and_register_element_id(
|
|
557
559
|
"plotly_chart",
|
|
558
560
|
user_key=key,
|
|
559
|
-
form_id=plotly_chart_proto.form_id,
|
|
560
561
|
dg=self.dg,
|
|
561
562
|
plotly_spec=plotly_chart_proto.spec,
|
|
562
563
|
plotly_config=plotly_chart_proto.config,
|
streamlit/elements/pyplot.py
CHANGED
|
@@ -19,8 +19,12 @@ from __future__ import annotations
|
|
|
19
19
|
import io
|
|
20
20
|
from typing import TYPE_CHECKING, Any, cast
|
|
21
21
|
|
|
22
|
-
from streamlit.deprecation_util import
|
|
23
|
-
|
|
22
|
+
from streamlit.deprecation_util import (
|
|
23
|
+
make_deprecated_name_warning,
|
|
24
|
+
show_deprecation_warning,
|
|
25
|
+
)
|
|
26
|
+
from streamlit.elements.lib.image_utils import marshall_images
|
|
27
|
+
from streamlit.elements.lib.layout_utils import LayoutConfig, Width, validate_width
|
|
24
28
|
from streamlit.proto.Image_pb2 import ImageList as ImageListProto
|
|
25
29
|
from streamlit.runtime.metrics_util import gather_metrics
|
|
26
30
|
|
|
@@ -36,7 +40,9 @@ class PyplotMixin:
|
|
|
36
40
|
self,
|
|
37
41
|
fig: Figure | None = None,
|
|
38
42
|
clear_figure: bool | None = None,
|
|
39
|
-
|
|
43
|
+
*,
|
|
44
|
+
width: Width = "stretch",
|
|
45
|
+
use_container_width: bool | None = None,
|
|
40
46
|
**kwargs: Any,
|
|
41
47
|
) -> DeltaGenerator:
|
|
42
48
|
"""Display a matplotlib.pyplot figure.
|
|
@@ -46,7 +52,9 @@ class PyplotMixin:
|
|
|
46
52
|
install all charting dependencies (except Bokeh) as an extra with
|
|
47
53
|
Streamlit:
|
|
48
54
|
|
|
49
|
-
|
|
55
|
+
.. code-block:: shell
|
|
56
|
+
|
|
57
|
+
pip install streamlit[charts]
|
|
50
58
|
|
|
51
59
|
Parameters
|
|
52
60
|
----------
|
|
@@ -69,6 +77,19 @@ class PyplotMixin:
|
|
|
69
77
|
- If ``fig`` is not set, defaults to ``True``. This simulates Jupyter's
|
|
70
78
|
approach to matplotlib rendering.
|
|
71
79
|
|
|
80
|
+
width : "stretch", "content", or int
|
|
81
|
+
The width of the chart element. This can be one of the following:
|
|
82
|
+
|
|
83
|
+
- ``"stretch"`` (default): The width of the element matches the
|
|
84
|
+
width of the parent container.
|
|
85
|
+
- ``"content"``: The width of the element matches the
|
|
86
|
+
width of its content, but doesn't exceed the width of the parent
|
|
87
|
+
container.
|
|
88
|
+
- An integer specifying the width in pixels: The element has a
|
|
89
|
+
fixed width. If the specified width is greater than the width of
|
|
90
|
+
the parent container, the width of the element matches the width
|
|
91
|
+
of the parent container.
|
|
92
|
+
|
|
72
93
|
use_container_width : bool
|
|
73
94
|
Whether to override the figure's native width with the width of
|
|
74
95
|
the parent container. If ``use_container_width`` is ``True``
|
|
@@ -81,6 +102,12 @@ class PyplotMixin:
|
|
|
81
102
|
**kwargs : any
|
|
82
103
|
Arguments to pass to Matplotlib's savefig function.
|
|
83
104
|
|
|
105
|
+
.. deprecated::
|
|
106
|
+
``use_container_width`` is deprecated and will be removed in a
|
|
107
|
+
future release. For ``use_container_width=True``, use
|
|
108
|
+
``width="stretch"``. For ``use_container_width=False``, use
|
|
109
|
+
``width="content"``.
|
|
110
|
+
|
|
84
111
|
Example
|
|
85
112
|
-------
|
|
86
113
|
>>> import matplotlib.pyplot as plt
|
|
@@ -106,6 +133,21 @@ class PyplotMixin:
|
|
|
106
133
|
|
|
107
134
|
"""
|
|
108
135
|
|
|
136
|
+
if use_container_width is not None:
|
|
137
|
+
show_deprecation_warning(
|
|
138
|
+
make_deprecated_name_warning(
|
|
139
|
+
"use_container_width",
|
|
140
|
+
"width",
|
|
141
|
+
"2025-12-31",
|
|
142
|
+
"For `use_container_width=True`, use `width='stretch'`. "
|
|
143
|
+
"For `use_container_width=False`, use `width='content'`.",
|
|
144
|
+
include_st_prefix=False,
|
|
145
|
+
),
|
|
146
|
+
show_in_browser=False,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
width = "stretch" if use_container_width else "content"
|
|
150
|
+
|
|
109
151
|
if not fig:
|
|
110
152
|
show_deprecation_warning("""
|
|
111
153
|
Calling `st.pyplot()` without providing a figure argument has been deprecated
|
|
@@ -125,16 +167,19 @@ If you have a specific use case that requires this functionality, please let us
|
|
|
125
167
|
know via [issue on Github](https://github.com/streamlit/streamlit/issues).
|
|
126
168
|
""")
|
|
127
169
|
|
|
170
|
+
validate_width(width, allow_content=True)
|
|
171
|
+
layout_config = LayoutConfig(width=width)
|
|
172
|
+
|
|
128
173
|
image_list_proto = ImageListProto()
|
|
129
174
|
marshall(
|
|
130
175
|
self.dg._get_delta_path_str(),
|
|
131
176
|
image_list_proto,
|
|
177
|
+
layout_config,
|
|
132
178
|
fig,
|
|
133
179
|
clear_figure,
|
|
134
|
-
use_container_width,
|
|
135
180
|
**kwargs,
|
|
136
181
|
)
|
|
137
|
-
return self.dg._enqueue("imgs", image_list_proto)
|
|
182
|
+
return self.dg._enqueue("imgs", image_list_proto, layout_config=layout_config)
|
|
138
183
|
|
|
139
184
|
@property
|
|
140
185
|
def dg(self) -> DeltaGenerator:
|
|
@@ -145,9 +190,9 @@ know via [issue on Github](https://github.com/streamlit/streamlit/issues).
|
|
|
145
190
|
def marshall(
|
|
146
191
|
coordinates: str,
|
|
147
192
|
image_list_proto: ImageListProto,
|
|
193
|
+
layout_config: LayoutConfig,
|
|
148
194
|
fig: Figure | None = None,
|
|
149
195
|
clear_figure: bool | None = True,
|
|
150
|
-
use_container_width: bool = True,
|
|
151
196
|
**kwargs: Any,
|
|
152
197
|
) -> None:
|
|
153
198
|
try:
|
|
@@ -178,14 +223,11 @@ def marshall(
|
|
|
178
223
|
|
|
179
224
|
image = io.BytesIO()
|
|
180
225
|
fig.savefig(image, **kwargs)
|
|
181
|
-
image_width = (
|
|
182
|
-
WidthBehavior.COLUMN if use_container_width else WidthBehavior.ORIGINAL
|
|
183
|
-
)
|
|
184
226
|
marshall_images(
|
|
185
227
|
coordinates=coordinates,
|
|
186
228
|
image=image,
|
|
187
229
|
caption=None,
|
|
188
|
-
|
|
230
|
+
layout_config=layout_config,
|
|
189
231
|
proto_imgs=image_list_proto,
|
|
190
232
|
clamp=False,
|
|
191
233
|
channels="RGB",
|