streamlit 1.49.1__py3-none-any.whl → 1.51.0__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 +4 -1
- streamlit/column_config.py +2 -0
- streamlit/commands/navigation.py +7 -7
- streamlit/commands/page_config.py +4 -6
- streamlit/components/v1/custom_component.py +17 -42
- streamlit/components/v2/__init__.py +458 -0
- streamlit/components/v2/bidi_component/__init__.py +20 -0
- streamlit/components/v2/bidi_component/constants.py +29 -0
- streamlit/components/v2/bidi_component/main.py +386 -0
- streamlit/components/v2/bidi_component/serialization.py +265 -0
- streamlit/components/v2/bidi_component/state.py +92 -0
- streamlit/components/v2/component_definition_resolver.py +143 -0
- streamlit/components/v2/component_file_watcher.py +403 -0
- streamlit/components/v2/component_manager.py +431 -0
- streamlit/components/v2/component_manifest_handler.py +122 -0
- streamlit/components/v2/component_path_utils.py +245 -0
- streamlit/components/v2/component_registry.py +409 -0
- streamlit/components/v2/get_bidi_component_manager.py +51 -0
- streamlit/components/v2/manifest_scanner.py +615 -0
- streamlit/components/v2/presentation.py +198 -0
- streamlit/components/v2/types.py +324 -0
- streamlit/config.py +741 -32
- streamlit/config_option.py +4 -1
- streamlit/config_util.py +650 -1
- streamlit/connections/base_connection.py +4 -2
- streamlit/dataframe_util.py +18 -10
- streamlit/delta_generator.py +8 -7
- streamlit/delta_generator_singletons.py +3 -1
- streamlit/deprecation_util.py +17 -6
- streamlit/elements/arrow.py +90 -42
- streamlit/elements/deck_gl_json_chart.py +98 -39
- streamlit/elements/dialog_decorator.py +2 -1
- streamlit/elements/exception.py +3 -1
- streamlit/elements/form.py +6 -6
- streamlit/elements/graphviz_chart.py +24 -9
- streamlit/elements/heading.py +3 -5
- streamlit/elements/iframe.py +0 -2
- streamlit/elements/image.py +12 -13
- streamlit/elements/layouts.py +89 -22
- streamlit/elements/lib/built_in_chart_utils.py +95 -31
- streamlit/elements/lib/color_util.py +8 -18
- streamlit/elements/lib/column_config_utils.py +9 -8
- streamlit/elements/lib/column_types.py +595 -148
- streamlit/elements/lib/dialog.py +3 -2
- streamlit/elements/lib/image_utils.py +3 -5
- streamlit/elements/lib/layout_utils.py +50 -13
- streamlit/elements/lib/mutable_status_container.py +2 -2
- streamlit/elements/lib/options_selector_utils.py +2 -2
- streamlit/elements/lib/pandas_styler_utils.py +30 -14
- streamlit/elements/lib/utils.py +21 -9
- streamlit/elements/map.py +81 -40
- streamlit/elements/media.py +7 -7
- streamlit/elements/metric.py +11 -35
- streamlit/elements/pdf.py +2 -4
- streamlit/elements/plotly_chart.py +142 -26
- streamlit/elements/progress.py +2 -4
- streamlit/elements/pyplot.py +6 -6
- streamlit/elements/space.py +113 -0
- streamlit/elements/vega_charts.py +400 -143
- streamlit/elements/widgets/audio_input.py +52 -4
- streamlit/elements/widgets/button.py +29 -29
- streamlit/elements/widgets/button_group.py +33 -6
- streamlit/elements/widgets/camera_input.py +3 -4
- streamlit/elements/widgets/chat.py +7 -0
- streamlit/elements/widgets/checkbox.py +1 -0
- streamlit/elements/widgets/color_picker.py +1 -0
- streamlit/elements/widgets/data_editor.py +34 -29
- streamlit/elements/widgets/file_uploader.py +6 -10
- streamlit/elements/widgets/multiselect.py +14 -3
- streamlit/elements/widgets/number_input.py +5 -4
- streamlit/elements/widgets/radio.py +10 -2
- streamlit/elements/widgets/select_slider.py +8 -4
- streamlit/elements/widgets/selectbox.py +9 -2
- streamlit/elements/widgets/slider.py +38 -41
- streamlit/elements/widgets/text_widgets.py +6 -0
- streamlit/elements/widgets/time_widgets.py +15 -12
- streamlit/elements/write.py +28 -23
- streamlit/emojis.py +1 -1
- streamlit/errors.py +115 -0
- streamlit/git_util.py +65 -43
- streamlit/hello/hello.py +8 -0
- streamlit/hello/utils.py +2 -1
- streamlit/material_icon_names.py +1 -1
- streamlit/navigation/page.py +4 -1
- streamlit/proto/ArrowData_pb2.py +27 -0
- streamlit/proto/ArrowData_pb2.pyi +46 -0
- streamlit/proto/Arrow_pb2.py +10 -8
- streamlit/proto/Arrow_pb2.pyi +31 -2
- streamlit/proto/AudioInput_pb2.py +2 -2
- streamlit/proto/AudioInput_pb2.pyi +6 -2
- streamlit/proto/BidiComponent_pb2.py +34 -0
- streamlit/proto/BidiComponent_pb2.pyi +153 -0
- streamlit/proto/Block_pb2.py +11 -11
- streamlit/proto/Block_pb2.pyi +9 -1
- streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
- streamlit/proto/DeckGlJsonChart_pb2.pyi +9 -3
- streamlit/proto/Element_pb2.py +5 -3
- streamlit/proto/Element_pb2.pyi +14 -4
- streamlit/proto/HeightConfig_pb2.py +2 -2
- streamlit/proto/HeightConfig_pb2.pyi +6 -3
- streamlit/proto/NewSession_pb2.py +18 -16
- streamlit/proto/NewSession_pb2.pyi +158 -6
- streamlit/proto/PlotlyChart_pb2.py +8 -6
- streamlit/proto/PlotlyChart_pb2.pyi +3 -1
- streamlit/proto/Space_pb2.py +27 -0
- streamlit/proto/Space_pb2.pyi +42 -0
- streamlit/proto/WidgetStates_pb2.py +2 -2
- streamlit/proto/WidgetStates_pb2.pyi +13 -3
- streamlit/proto/WidthConfig_pb2.py +2 -2
- streamlit/proto/WidthConfig_pb2.pyi +6 -3
- streamlit/runtime/app_session.py +45 -6
- streamlit/runtime/caching/cache_data_api.py +4 -4
- streamlit/runtime/caching/cache_errors.py +4 -1
- streamlit/runtime/caching/cache_resource_api.py +3 -2
- streamlit/runtime/caching/cache_utils.py +2 -1
- streamlit/runtime/caching/cached_message_replay.py +3 -3
- streamlit/runtime/caching/hashing.py +3 -4
- streamlit/runtime/caching/legacy_cache_api.py +2 -1
- streamlit/runtime/connection_factory.py +1 -3
- streamlit/runtime/forward_msg_queue.py +4 -1
- streamlit/runtime/fragment.py +2 -1
- streamlit/runtime/memory_media_file_storage.py +1 -1
- streamlit/runtime/metrics_util.py +6 -2
- streamlit/runtime/runtime.py +14 -0
- streamlit/runtime/scriptrunner/exec_code.py +2 -1
- streamlit/runtime/scriptrunner/script_runner.py +2 -2
- streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
- streamlit/runtime/secrets.py +2 -4
- streamlit/runtime/session_manager.py +3 -1
- streamlit/runtime/state/common.py +30 -5
- streamlit/runtime/state/presentation.py +85 -0
- streamlit/runtime/state/safe_session_state.py +2 -2
- streamlit/runtime/state/session_state.py +220 -16
- streamlit/runtime/state/widgets.py +19 -3
- streamlit/runtime/theme_util.py +148 -0
- streamlit/runtime/websocket_session_manager.py +3 -1
- streamlit/source_util.py +2 -2
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +244 -227
- streamlit/static/static/css/{index.C8X8rNzw.css → index.BpABIXK9.css} +1 -1
- streamlit/static/static/css/index.DgR7E2CV.css +1 -0
- streamlit/static/static/js/{ErrorOutline.esm.DcGrhbBP.js → ErrorOutline.esm.YoJdlW1p.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.DgBvV6Pq.js → FileDownload.esm.Ddx8VEYy.js} +1 -1
- streamlit/static/static/js/{FileHelper.M6AAaeuA.js → FileHelper.90EtOmj9.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.DHh1GFzm.js → FormClearHelper.BB1Km6eP.js} +1 -1
- streamlit/static/static/js/InputInstructions.jhH15PqV.js +1 -0
- streamlit/static/static/js/{Particles.DDVT-6Qc.js → Particles.DUsputn1.js} +1 -1
- streamlit/static/static/js/{ProgressBar.BEY0cXXV.js → ProgressBar.DLY8H6nE.js} +2 -2
- streamlit/static/static/js/Toolbar.D8nHCkuz.js +1 -0
- streamlit/static/static/js/{base-input.CK3UVGp1.js → base-input.CJGiNqed.js} +3 -3
- streamlit/static/static/js/{checkbox.D8W881TL.js → checkbox.Cpdd482O.js} +1 -1
- streamlit/static/static/js/{createSuper.B6W-Dh9S.js → createSuper.CuQIogbW.js} +1 -1
- streamlit/static/static/js/data-grid-overlay-editor.2Ufgxc6y.js +1 -0
- streamlit/static/static/js/{downloader.DiKpuU_S.js → downloader.CN0K7xlu.js} +1 -1
- streamlit/static/static/js/{es6.B8zRNPZ-.js → es6.BJcsVXQ0.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.DIewJmmh.js → iframeResizer.contentWindow.XzUvQqcZ.js} +1 -1
- streamlit/static/static/js/index.B1ZQh4P1.js +1 -0
- streamlit/static/static/js/index.BKstZk0M.js +27 -0
- streamlit/static/static/js/{index.Bte_9Lyq.js → index.BMcFsUee.js} +1 -1
- streamlit/static/static/js/{index.qhs54UAB.js → index.BR-IdcTb.js} +1 -1
- streamlit/static/static/js/{index.CejBxbg1.js → index.B_dWA3vd.js} +1 -1
- streamlit/static/static/js/{index.D5naqx-J.js → index.BgnZEMVh.js} +1 -1
- streamlit/static/static/js/{index.C7fRKRs4.js → index.BohqXifI.js} +1 -1
- streamlit/static/static/js/{index.cnnXF7xQ.js → index.Br5nxKNj.js} +1 -1
- streamlit/static/static/js/index.BrIKVbNc.js +3 -0
- streamlit/static/static/js/index.BtWUPzle.js +1 -0
- streamlit/static/static/js/index.C0RLraek.js +1 -0
- streamlit/static/static/js/{index.CP5TD2z1.js → index.CAIjskgG.js} +1 -1
- streamlit/static/static/js/{index.CD8HuT3N.js → index.CAj-7vWz.js} +135 -162
- streamlit/static/static/js/{index.DtYN2x4k.js → index.CMtEit2O.js} +1 -1
- streamlit/static/static/js/index.CkRlykEE.js +12 -0
- streamlit/static/static/js/{index.Ts_0SdB9.js → index.CmN3FXfI.js} +2 -2
- streamlit/static/static/js/{index.BnEpvLEz.js → index.CwbFI1_-.js} +1 -1
- streamlit/static/static/js/{index.CcJf6BCU.js → index.CxIUUfab.js} +27 -27
- streamlit/static/static/js/index.D2KPNy7e.js +1 -0
- streamlit/static/static/js/{index.Ch7MBCx0.js → index.D3GPA5k4.js} +47 -47
- streamlit/static/static/js/{index.ho6NIXGl.js → index.DGAh7DMq.js} +1 -1
- streamlit/static/static/js/index.DKb_NvmG.js +197 -0
- streamlit/static/static/js/{index.CvYYtxD_.js → index.DMqgUYKq.js} +1 -1
- streamlit/static/static/js/{index.zecpGxtj.js → index.DOFlg3dS.js} +1 -1
- streamlit/static/static/js/{index.B9mjBcgE.js → index.DPUXkcQL.js} +1 -1
- streamlit/static/static/js/index.DX1xY89g.js +1 -0
- streamlit/static/static/js/index.DYATBCsq.js +2 -0
- streamlit/static/static/js/{index.D2-atlaQ.js → index.DaSmGJ76.js} +3 -3
- streamlit/static/static/js/index.Dd7bMeLP.js +1 -0
- streamlit/static/static/js/{index.4eF4NxG2.js → index.DjmmgI5U.js} +1 -1
- streamlit/static/static/js/index.Dq56CyM2.js +1 -0
- streamlit/static/static/js/index.DuiXaS5_.js +7 -0
- streamlit/static/static/js/index.DvFidMLe.js +2 -0
- streamlit/static/static/js/{index.452cqrrL.js → index.DwkhC5Pc.js} +1 -1
- streamlit/static/static/js/{index.Dk4C7X3i.js → index.Q-3sFn1v.js} +1 -1
- streamlit/static/static/js/{index.CjXWwH-y.js → index.QJ5QO9sJ.js} +1 -1
- streamlit/static/static/js/{index.B6U8LQo3.js → index.VwTaeety.js} +1 -1
- streamlit/static/static/js/index.YOqQbeX8.js +1 -0
- streamlit/static/static/js/{input.nzVJphXi.js → input.D4MN_FzN.js} +1 -1
- streamlit/static/static/js/{memory.CjCgTQz3.js → memory.DrZjtdGT.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.DaRFzZEO.js → number-overlay-editor.DRwAw1In.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.DgiPnZ9N.js → possibleConstructorReturn.exeeJQEP.js} +1 -1
- streamlit/static/static/js/record.B-tDciZb.js +1 -0
- streamlit/static/static/js/{sandbox.mithfq7Z.js → sandbox.ClO3IuUr.js} +1 -1
- streamlit/static/static/js/{timepicker.Dbl5KFh6.js → timepicker.DAhu-vcF.js} +4 -4
- streamlit/static/static/js/{toConsumableArray.D-Dx88BQ.js → toConsumableArray.DNbljYEC.js} +1 -1
- streamlit/static/static/js/{uniqueId.Bh26R_3S.js → uniqueId.oG4Gvj1v.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.DeK-QJpD.js → useBasicWidgetState.D6sOH6oI.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.4iAdLWD-.js → useTextInputAutoExpand.4u3_GcuN.js} +2 -2
- streamlit/static/static/js/{useUpdateUiValue.CmT7_nJN.js → useUpdateUiValue.F2R3eTeR.js} +1 -1
- streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
- streamlit/static/static/js/withFullScreenWrapper.zothJIsI.js +1 -0
- streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
- streamlit/string_util.py +56 -1
- streamlit/testing/v1/app_test.py +2 -2
- streamlit/testing/v1/element_tree.py +23 -9
- streamlit/testing/v1/util.py +2 -2
- streamlit/type_util.py +3 -4
- streamlit/url_util.py +1 -3
- streamlit/user_info.py +1 -2
- streamlit/util.py +3 -1
- streamlit/watcher/event_based_path_watcher.py +23 -12
- streamlit/watcher/local_sources_watcher.py +11 -1
- streamlit/watcher/path_watcher.py +9 -6
- streamlit/watcher/polling_path_watcher.py +4 -1
- streamlit/watcher/util.py +2 -2
- streamlit/web/bootstrap.py +0 -31
- streamlit/web/cli.py +51 -22
- streamlit/web/server/bidi_component_request_handler.py +193 -0
- streamlit/web/server/component_file_utils.py +97 -0
- streamlit/web/server/component_request_handler.py +8 -21
- streamlit/web/server/oidc_mixin.py +3 -1
- streamlit/web/server/routes.py +18 -5
- streamlit/web/server/server.py +10 -0
- streamlit/web/server/server_util.py +3 -1
- streamlit/web/server/upload_file_request_handler.py +3 -1
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/METADATA +4 -5
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/RECORD +238 -209
- streamlit/static/static/css/index.COe1010n.css +0 -1
- streamlit/static/static/js/Hooks.DGu1od_L.js +0 -1
- streamlit/static/static/js/InputInstructions.z6sVgyYt.js +0 -1
- streamlit/static/static/js/Toolbar.DSnK1fUh.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.DRTHOydk.js +0 -1
- streamlit/static/static/js/index.BXYmrqnf.js +0 -1
- streamlit/static/static/js/index.B_8AnktO.js +0 -1
- streamlit/static/static/js/index.Bl7zGQSh.js +0 -7
- streamlit/static/static/js/index.BnJIOYn9.js +0 -73
- streamlit/static/static/js/index.C1HcTl5K.js +0 -1
- streamlit/static/static/js/index.C7lSmSOP.js +0 -1
- streamlit/static/static/js/index.C_tmcx4B.js +0 -1
- streamlit/static/static/js/index.D3K5nOu9.js +0 -197
- streamlit/static/static/js/index.DkKT3LUI.js +0 -1
- streamlit/static/static/js/index.MTPPBDHk.js +0 -2
- streamlit/static/static/js/index.pqW9AMJD.js +0 -3
- streamlit/static/static/js/index.urHgTgMQ.js +0 -12
- streamlit/static/static/js/index.wzkv_11M.js +0 -1
- streamlit/static/static/js/index.yF5AncHY.js +0 -1
- streamlit/static/static/js/withFullScreenWrapper.DLp1ENGm.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.CBxVaFdk.woff2 +0 -0
- {streamlit-1.49.1.data → streamlit-1.51.0.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/WHEEL +0 -0
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/entry_points.txt +0 -0
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/top_level.txt +0 -0
|
@@ -19,7 +19,6 @@ from textwrap import dedent
|
|
|
19
19
|
from typing import (
|
|
20
20
|
TYPE_CHECKING,
|
|
21
21
|
Any,
|
|
22
|
-
Callable,
|
|
23
22
|
Generic,
|
|
24
23
|
Literal,
|
|
25
24
|
TypeVar,
|
|
@@ -64,7 +63,7 @@ from streamlit.type_util import (
|
|
|
64
63
|
)
|
|
65
64
|
|
|
66
65
|
if TYPE_CHECKING:
|
|
67
|
-
from collections.abc import Sequence
|
|
66
|
+
from collections.abc import Callable, Sequence
|
|
68
67
|
|
|
69
68
|
from streamlit.dataframe_util import OptionSequence
|
|
70
69
|
from streamlit.delta_generator import DeltaGenerator
|
|
@@ -370,7 +369,9 @@ class MultiSelectMixin:
|
|
|
370
369
|
Returns
|
|
371
370
|
-------
|
|
372
371
|
list
|
|
373
|
-
A list
|
|
372
|
+
A list of the selected options.
|
|
373
|
+
|
|
374
|
+
The list contains copies of the selected options, not the originals.
|
|
374
375
|
|
|
375
376
|
Examples
|
|
376
377
|
--------
|
|
@@ -492,6 +493,16 @@ class MultiSelectMixin:
|
|
|
492
493
|
element_id = compute_and_register_element_id(
|
|
493
494
|
widget_name,
|
|
494
495
|
user_key=key,
|
|
496
|
+
# Treat the provided key as the main identity. Only include
|
|
497
|
+
# changes to the options, accept_new_options, and max_selections
|
|
498
|
+
# in the identity computation as those can invalidate the
|
|
499
|
+
# current selection.
|
|
500
|
+
key_as_main_identity={
|
|
501
|
+
"options",
|
|
502
|
+
"max_selections",
|
|
503
|
+
"accept_new_options",
|
|
504
|
+
"format_func",
|
|
505
|
+
},
|
|
495
506
|
dg=self.dg,
|
|
496
507
|
label=label,
|
|
497
508
|
options=formatted_options,
|
|
@@ -17,9 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
import numbers
|
|
18
18
|
from dataclasses import dataclass
|
|
19
19
|
from textwrap import dedent
|
|
20
|
-
from typing import TYPE_CHECKING, Literal,
|
|
21
|
-
|
|
22
|
-
from typing_extensions import TypeAlias
|
|
20
|
+
from typing import TYPE_CHECKING, Literal, TypeAlias, TypeVar, cast, overload
|
|
23
21
|
|
|
24
22
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
25
23
|
from streamlit.elements.lib.js_number import JSNumber, JSNumberBoundsException
|
|
@@ -62,7 +60,7 @@ if TYPE_CHECKING:
|
|
|
62
60
|
from streamlit.delta_generator import DeltaGenerator
|
|
63
61
|
|
|
64
62
|
|
|
65
|
-
Number: TypeAlias =
|
|
63
|
+
Number: TypeAlias = int | float
|
|
66
64
|
IntOrNone = TypeVar("IntOrNone", int, None)
|
|
67
65
|
FloatOrNone = TypeVar("FloatOrNone", float, None)
|
|
68
66
|
|
|
@@ -452,6 +450,9 @@ class NumberInputMixin:
|
|
|
452
450
|
element_id = compute_and_register_element_id(
|
|
453
451
|
"number_input",
|
|
454
452
|
user_key=key,
|
|
453
|
+
# Ensure stable ID when key is provided; explicitly whitelist parameters
|
|
454
|
+
# that might invalidate the current widget state.
|
|
455
|
+
key_as_main_identity={"min_value", "max_value", "step"},
|
|
455
456
|
dg=self.dg,
|
|
456
457
|
label=label,
|
|
457
458
|
min_value=min_value,
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
from dataclasses import dataclass
|
|
18
18
|
from textwrap import dedent
|
|
19
|
-
from typing import TYPE_CHECKING, Any,
|
|
19
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast, overload
|
|
20
20
|
|
|
21
21
|
from typing_extensions import Never
|
|
22
22
|
|
|
@@ -56,7 +56,7 @@ from streamlit.type_util import (
|
|
|
56
56
|
)
|
|
57
57
|
|
|
58
58
|
if TYPE_CHECKING:
|
|
59
|
-
from collections.abc import Sequence
|
|
59
|
+
from collections.abc import Callable, Sequence
|
|
60
60
|
|
|
61
61
|
from streamlit.delta_generator import DeltaGenerator
|
|
62
62
|
|
|
@@ -272,6 +272,8 @@ class RadioMixin:
|
|
|
272
272
|
any
|
|
273
273
|
The selected option or ``None`` if no option is selected.
|
|
274
274
|
|
|
275
|
+
This is a copy of the selected option, not the original.
|
|
276
|
+
|
|
275
277
|
Example
|
|
276
278
|
-------
|
|
277
279
|
>>> import streamlit as st
|
|
@@ -369,6 +371,12 @@ class RadioMixin:
|
|
|
369
371
|
element_id = compute_and_register_element_id(
|
|
370
372
|
"radio",
|
|
371
373
|
user_key=key,
|
|
374
|
+
# Treat provided key as the main widget identity. Only include the
|
|
375
|
+
# following parameters in the identity computation since they can
|
|
376
|
+
# invalidate the current selection mapping.
|
|
377
|
+
# Changes to format_func also invalidate the current selection,
|
|
378
|
+
# but this is already handled via the `options` parameter below:
|
|
379
|
+
key_as_main_identity={"options"},
|
|
372
380
|
dg=self.dg,
|
|
373
381
|
label=label,
|
|
374
382
|
options=[str(format_func(option)) for option in opt],
|
|
@@ -19,15 +19,13 @@ from textwrap import dedent
|
|
|
19
19
|
from typing import (
|
|
20
20
|
TYPE_CHECKING,
|
|
21
21
|
Any,
|
|
22
|
-
Callable,
|
|
23
22
|
Generic,
|
|
23
|
+
TypeGuard,
|
|
24
24
|
TypeVar,
|
|
25
25
|
cast,
|
|
26
26
|
overload,
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
-
from typing_extensions import TypeGuard
|
|
30
|
-
|
|
31
29
|
from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
|
|
32
30
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
33
31
|
from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
|
|
@@ -61,7 +59,7 @@ from streamlit.runtime.state import (
|
|
|
61
59
|
from streamlit.type_util import check_python_comparable
|
|
62
60
|
|
|
63
61
|
if TYPE_CHECKING:
|
|
64
|
-
from collections.abc import Sequence
|
|
62
|
+
from collections.abc import Callable, Sequence
|
|
65
63
|
|
|
66
64
|
from streamlit.delta_generator import DeltaGenerator
|
|
67
65
|
from streamlit.elements.lib.layout_utils import WidthWithoutContent
|
|
@@ -264,6 +262,8 @@ class SelectSliderMixin:
|
|
|
264
262
|
The current value of the slider widget. The return type will match
|
|
265
263
|
the data type of the value parameter.
|
|
266
264
|
|
|
265
|
+
This contains copies of the selected options, not the originals.
|
|
266
|
+
|
|
267
267
|
Examples
|
|
268
268
|
--------
|
|
269
269
|
>>> import streamlit as st
|
|
@@ -377,6 +377,10 @@ class SelectSliderMixin:
|
|
|
377
377
|
element_id = compute_and_register_element_id(
|
|
378
378
|
"select_slider",
|
|
379
379
|
user_key=key,
|
|
380
|
+
# Treat the provided key as the main identity; only include
|
|
381
|
+
# changes to the options (and implicitly their formatting) in the
|
|
382
|
+
# identity computation as those can invalidate the current value.
|
|
383
|
+
key_as_main_identity={"options", "format_func"},
|
|
380
384
|
dg=self.dg,
|
|
381
385
|
label=label,
|
|
382
386
|
options=[str(format_func(option)) for option in opt],
|
|
@@ -17,7 +17,6 @@ from textwrap import dedent
|
|
|
17
17
|
from typing import (
|
|
18
18
|
TYPE_CHECKING,
|
|
19
19
|
Any,
|
|
20
|
-
Callable,
|
|
21
20
|
Generic,
|
|
22
21
|
Literal,
|
|
23
22
|
TypeVar,
|
|
@@ -67,7 +66,7 @@ from streamlit.type_util import (
|
|
|
67
66
|
)
|
|
68
67
|
|
|
69
68
|
if TYPE_CHECKING:
|
|
70
|
-
from collections.abc import Sequence
|
|
69
|
+
from collections.abc import Callable, Sequence
|
|
71
70
|
|
|
72
71
|
from streamlit.delta_generator import DeltaGenerator
|
|
73
72
|
|
|
@@ -404,6 +403,8 @@ class SelectboxMixin:
|
|
|
404
403
|
any
|
|
405
404
|
The selected option or ``None`` if no option is selected.
|
|
406
405
|
|
|
406
|
+
This is a copy of the selected option, not the original.
|
|
407
|
+
|
|
407
408
|
Examples
|
|
408
409
|
--------
|
|
409
410
|
**Example 1: Use a basic selectbox widget**
|
|
@@ -541,6 +542,12 @@ class SelectboxMixin:
|
|
|
541
542
|
element_id = compute_and_register_element_id(
|
|
542
543
|
"selectbox",
|
|
543
544
|
user_key=key,
|
|
545
|
+
# Treat the provided key as the main identity. Only include
|
|
546
|
+
# the options and accept_new_options in the identity computation
|
|
547
|
+
# as those can invalidate the current selection.
|
|
548
|
+
# Changes to format_func also invalidate the current selection,
|
|
549
|
+
# but this is already handled via the `options` parameter below:
|
|
550
|
+
key_as_main_identity={"options", "accept_new_options"},
|
|
544
551
|
dg=self.dg,
|
|
545
552
|
label=label,
|
|
546
553
|
options=formatted_options,
|
|
@@ -23,15 +23,13 @@ from typing import (
|
|
|
23
23
|
TYPE_CHECKING,
|
|
24
24
|
Any,
|
|
25
25
|
Final,
|
|
26
|
+
TypeAlias,
|
|
26
27
|
TypedDict,
|
|
27
28
|
TypeVar,
|
|
28
|
-
Union,
|
|
29
29
|
cast,
|
|
30
30
|
overload,
|
|
31
31
|
)
|
|
32
32
|
|
|
33
|
-
from typing_extensions import TypeAlias
|
|
34
|
-
|
|
35
33
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
36
34
|
from streamlit.elements.lib.js_number import JSNumber, JSNumberBoundsException
|
|
37
35
|
from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
|
|
@@ -69,48 +67,43 @@ if TYPE_CHECKING:
|
|
|
69
67
|
SliderNumericT = TypeVar("SliderNumericT", int, float)
|
|
70
68
|
SliderDatelikeT = TypeVar("SliderDatelikeT", date, time, datetime)
|
|
71
69
|
|
|
72
|
-
SliderNumericSpanT: TypeAlias =
|
|
73
|
-
list[SliderNumericT]
|
|
74
|
-
tuple[()]
|
|
75
|
-
tuple[SliderNumericT]
|
|
76
|
-
tuple[SliderNumericT, SliderNumericT]
|
|
77
|
-
|
|
78
|
-
SliderDatelikeSpanT: TypeAlias =
|
|
79
|
-
list[SliderDatelikeT]
|
|
80
|
-
tuple[()]
|
|
81
|
-
tuple[SliderDatelikeT]
|
|
82
|
-
tuple[SliderDatelikeT, SliderDatelikeT]
|
|
83
|
-
|
|
70
|
+
SliderNumericSpanT: TypeAlias = (
|
|
71
|
+
list[SliderNumericT]
|
|
72
|
+
| tuple[()]
|
|
73
|
+
| tuple[SliderNumericT]
|
|
74
|
+
| tuple[SliderNumericT, SliderNumericT]
|
|
75
|
+
)
|
|
76
|
+
SliderDatelikeSpanT: TypeAlias = (
|
|
77
|
+
list[SliderDatelikeT]
|
|
78
|
+
| tuple[()]
|
|
79
|
+
| tuple[SliderDatelikeT]
|
|
80
|
+
| tuple[SliderDatelikeT, SliderDatelikeT]
|
|
81
|
+
)
|
|
84
82
|
|
|
85
83
|
StepNumericT: TypeAlias = SliderNumericT
|
|
86
84
|
StepDatelikeT: TypeAlias = timedelta
|
|
87
85
|
|
|
88
|
-
SliderStep: TypeAlias =
|
|
89
|
-
SliderScalar: TypeAlias =
|
|
86
|
+
SliderStep: TypeAlias = int | float | timedelta
|
|
87
|
+
SliderScalar: TypeAlias = int | float | date | time | datetime
|
|
90
88
|
SliderValueT = TypeVar("SliderValueT", int, float, date, time, datetime)
|
|
91
|
-
SliderValueGeneric: TypeAlias =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
SliderValueGeneric[
|
|
97
|
-
SliderValueGeneric[
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
]
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
SliderReturnGeneric[float],
|
|
110
|
-
SliderReturnGeneric[date],
|
|
111
|
-
SliderReturnGeneric[time],
|
|
112
|
-
SliderReturnGeneric[datetime],
|
|
113
|
-
]
|
|
89
|
+
SliderValueGeneric: TypeAlias = SliderValueT | Sequence[SliderValueT]
|
|
90
|
+
SliderValue: TypeAlias = (
|
|
91
|
+
SliderValueGeneric[int]
|
|
92
|
+
| SliderValueGeneric[float] # ty: ignore
|
|
93
|
+
| SliderValueGeneric[date]
|
|
94
|
+
| SliderValueGeneric[time]
|
|
95
|
+
| SliderValueGeneric[datetime]
|
|
96
|
+
)
|
|
97
|
+
SliderReturnGeneric: TypeAlias = (
|
|
98
|
+
SliderValueT | tuple[SliderValueT] | tuple[SliderValueT, SliderValueT]
|
|
99
|
+
)
|
|
100
|
+
SliderReturn: TypeAlias = (
|
|
101
|
+
SliderReturnGeneric[int]
|
|
102
|
+
| SliderReturnGeneric[float] # ty: ignore
|
|
103
|
+
| SliderReturnGeneric[date]
|
|
104
|
+
| SliderReturnGeneric[time]
|
|
105
|
+
| SliderReturnGeneric[datetime]
|
|
106
|
+
)
|
|
114
107
|
|
|
115
108
|
SECONDS_TO_MICROS: Final = 1000 * 1000
|
|
116
109
|
DAYS_TO_MICROS: Final = 24 * 60 * 60 * SECONDS_TO_MICROS
|
|
@@ -680,6 +673,10 @@ class SliderMixin:
|
|
|
680
673
|
element_id = compute_and_register_element_id(
|
|
681
674
|
"slider",
|
|
682
675
|
user_key=key,
|
|
676
|
+
# Treat the provided key as the main identity; only include
|
|
677
|
+
# changes to the value-shaping arguments in the identity
|
|
678
|
+
# computation as those can invalidate the current value.
|
|
679
|
+
key_as_main_identity={"min_value", "max_value", "step"},
|
|
683
680
|
dg=self.dg,
|
|
684
681
|
label=label,
|
|
685
682
|
min_value=min_value,
|
|
@@ -801,7 +798,7 @@ class SliderMixin:
|
|
|
801
798
|
if data_type in (
|
|
802
799
|
SliderProto.DATETIME,
|
|
803
800
|
SliderProto.DATE,
|
|
804
|
-
) and max_value - min_value < timedelta(days=1):
|
|
801
|
+
) and max_value - min_value < timedelta(days=1): # ty: ignore[unsupported-operator]
|
|
805
802
|
step = timedelta(minutes=15)
|
|
806
803
|
if format is None:
|
|
807
804
|
format = cast("str", defaults[data_type]["format"]) # noqa: A001
|
|
@@ -328,6 +328,9 @@ class TextWidgetsMixin:
|
|
|
328
328
|
element_id = compute_and_register_element_id(
|
|
329
329
|
"text_input",
|
|
330
330
|
user_key=key,
|
|
331
|
+
# Explicitly whitelist max_chars to make sure the ID changes when it changes
|
|
332
|
+
# since the widget value might become invalid based on a different max_chars
|
|
333
|
+
key_as_main_identity={"max_chars"},
|
|
331
334
|
dg=self.dg,
|
|
332
335
|
label=label,
|
|
333
336
|
value=value,
|
|
@@ -642,6 +645,9 @@ class TextWidgetsMixin:
|
|
|
642
645
|
element_id = compute_and_register_element_id(
|
|
643
646
|
"text_area",
|
|
644
647
|
user_key=key,
|
|
648
|
+
# Explicitly whitelist max_chars to make sure the ID changes when it changes
|
|
649
|
+
# since the widget value might become invalid based on a different max_chars
|
|
650
|
+
key_as_main_identity={"max_chars"},
|
|
645
651
|
dg=self.dg,
|
|
646
652
|
label=label,
|
|
647
653
|
value=value,
|
|
@@ -23,13 +23,11 @@ from typing import (
|
|
|
23
23
|
Any,
|
|
24
24
|
Final,
|
|
25
25
|
Literal,
|
|
26
|
-
|
|
26
|
+
TypeAlias,
|
|
27
27
|
cast,
|
|
28
28
|
overload,
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
-
from typing_extensions import TypeAlias
|
|
32
|
-
|
|
33
31
|
from streamlit.elements.lib.form_utils import current_form_id
|
|
34
32
|
from streamlit.elements.lib.layout_utils import (
|
|
35
33
|
LayoutConfig,
|
|
@@ -65,21 +63,17 @@ if TYPE_CHECKING:
|
|
|
65
63
|
from streamlit.delta_generator import DeltaGenerator
|
|
66
64
|
|
|
67
65
|
# Type for things that point to a specific time (even if a default time, though not None).
|
|
68
|
-
TimeValue: TypeAlias =
|
|
66
|
+
TimeValue: TypeAlias = time | datetime | str | Literal["now"]
|
|
69
67
|
|
|
70
68
|
# Type for things that point to a specific date (even if a default date, including None).
|
|
71
|
-
NullableScalarDateValue: TypeAlias =
|
|
69
|
+
NullableScalarDateValue: TypeAlias = date | datetime | str | Literal["today"] | None
|
|
72
70
|
|
|
73
71
|
# The accepted input value for st.date_input. Can be a date scalar or a date range.
|
|
74
|
-
DateValue: TypeAlias =
|
|
72
|
+
DateValue: TypeAlias = NullableScalarDateValue | Sequence[NullableScalarDateValue]
|
|
75
73
|
|
|
76
74
|
# The return value of st.date_input.
|
|
77
|
-
DateWidgetRangeReturn: TypeAlias =
|
|
78
|
-
|
|
79
|
-
tuple[date],
|
|
80
|
-
tuple[date, date],
|
|
81
|
-
]
|
|
82
|
-
DateWidgetReturn: TypeAlias = Union[date, DateWidgetRangeReturn, None]
|
|
75
|
+
DateWidgetRangeReturn: TypeAlias = tuple[()] | tuple[date] | tuple[date, date]
|
|
76
|
+
DateWidgetReturn: TypeAlias = date | DateWidgetRangeReturn | None
|
|
83
77
|
|
|
84
78
|
|
|
85
79
|
DEFAULT_STEP_MINUTES: Final = 15
|
|
@@ -529,6 +523,9 @@ class TimeWidgetsMixin:
|
|
|
529
523
|
element_id = compute_and_register_element_id(
|
|
530
524
|
"time_input",
|
|
531
525
|
user_key=key,
|
|
526
|
+
# Ensure stable ID when key is provided; only whitelist step since it
|
|
527
|
+
# affects the selection granularity and available options.
|
|
528
|
+
key_as_main_identity={"step"},
|
|
532
529
|
dg=self.dg,
|
|
533
530
|
label=label,
|
|
534
531
|
value=parsed_time if isinstance(value, (datetime, time)) else value,
|
|
@@ -911,6 +908,12 @@ class TimeWidgetsMixin:
|
|
|
911
908
|
element_id = compute_and_register_element_id(
|
|
912
909
|
"date_input",
|
|
913
910
|
user_key=key,
|
|
911
|
+
# Ensure stable ID when key is provided; explicitly whitelist parameters
|
|
912
|
+
# that might invalidate the current widget state.
|
|
913
|
+
# format should be supported. However, there is a bug in baseweb where
|
|
914
|
+
# changing the format dynamically leads to a wrongly formatted date.
|
|
915
|
+
# So, we whitelist it for now until we migrate this away from baseweb.
|
|
916
|
+
key_as_main_identity={"min_value", "max_value", "format"},
|
|
914
917
|
dg=self.dg,
|
|
915
918
|
label=label,
|
|
916
919
|
value=parsed,
|
streamlit/elements/write.py
CHANGED
|
@@ -20,6 +20,7 @@ import types
|
|
|
20
20
|
from collections import ChainMap, UserDict, UserList
|
|
21
21
|
from collections.abc import (
|
|
22
22
|
AsyncGenerator,
|
|
23
|
+
Callable,
|
|
23
24
|
Generator,
|
|
24
25
|
ItemsView,
|
|
25
26
|
Iterable,
|
|
@@ -30,14 +31,12 @@ from io import StringIO
|
|
|
30
31
|
from typing import (
|
|
31
32
|
TYPE_CHECKING,
|
|
32
33
|
Any,
|
|
33
|
-
Callable,
|
|
34
34
|
Final,
|
|
35
35
|
cast,
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
from streamlit import dataframe_util, type_util
|
|
39
39
|
from streamlit.errors import StreamlitAPIException
|
|
40
|
-
from streamlit.logger import get_logger
|
|
41
40
|
from streamlit.runtime.metrics_util import gather_metrics
|
|
42
41
|
from streamlit.string_util import (
|
|
43
42
|
is_mem_address_str,
|
|
@@ -56,10 +55,6 @@ HELP_TYPES: Final[tuple[type[Any], ...]] = (
|
|
|
56
55
|
types.ModuleType,
|
|
57
56
|
)
|
|
58
57
|
|
|
59
|
-
_LOGGER: Final = get_logger(__name__)
|
|
60
|
-
|
|
61
|
-
_TEXT_CURSOR: Final = " ▏"
|
|
62
|
-
|
|
63
58
|
|
|
64
59
|
class StreamingOutput(list[Any]):
|
|
65
60
|
pass
|
|
@@ -73,8 +68,10 @@ class WriteMixin:
|
|
|
73
68
|
| Generator[Any, Any, Any]
|
|
74
69
|
| Iterable[Any]
|
|
75
70
|
| AsyncGenerator[Any, Any],
|
|
71
|
+
*,
|
|
72
|
+
cursor: str | None = None,
|
|
76
73
|
) -> list[Any] | str:
|
|
77
|
-
"""Stream a generator, iterable, or stream-like sequence to the app.
|
|
74
|
+
r"""Stream a generator, iterable, or stream-like sequence to the app.
|
|
78
75
|
|
|
79
76
|
``st.write_stream`` iterates through the given sequences and writes all
|
|
80
77
|
chunks to the app. String chunks will be written using a typewriter effect.
|
|
@@ -94,6 +91,27 @@ class WriteMixin:
|
|
|
94
91
|
manually define a generator function and include custom output
|
|
95
92
|
parsing.
|
|
96
93
|
|
|
94
|
+
cursor : str or None
|
|
95
|
+
A string to append to text as it's being written. If this is
|
|
96
|
+
``None`` (default), no cursor is shown. Otherwise, the string is
|
|
97
|
+
rendered as Markdown and appears as a cursor at the end of the
|
|
98
|
+
streamed text. For example, you can use an emoji, emoji shortcode,
|
|
99
|
+
or Material icon.
|
|
100
|
+
|
|
101
|
+
The first line of the cursor string can contain GitHub-flavored
|
|
102
|
+
Markdown of the following types: Bold, Italics, Strikethroughs,
|
|
103
|
+
Inline Code, Links, and Images. Images display like icons, with a
|
|
104
|
+
max height equal to the font height. If you pass a multiline
|
|
105
|
+
string, additional lines display after the text with the full
|
|
106
|
+
Markdown rendering capabilities of ``st.markdown``.
|
|
107
|
+
|
|
108
|
+
See the ``body`` parameter of |st.markdown|_ for additional,
|
|
109
|
+
supported Markdown directives.
|
|
110
|
+
|
|
111
|
+
.. |st.markdown| replace:: ``st.markdown``
|
|
112
|
+
.. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
|
|
113
|
+
|
|
114
|
+
|
|
97
115
|
Returns
|
|
98
116
|
-------
|
|
99
117
|
str or list
|
|
@@ -153,6 +171,7 @@ class WriteMixin:
|
|
|
153
171
|
"this data type."
|
|
154
172
|
)
|
|
155
173
|
|
|
174
|
+
cursor_str = cursor or ""
|
|
156
175
|
stream_container: DeltaGenerator | None = None
|
|
157
176
|
streamed_response: str = ""
|
|
158
177
|
written_content: list[Any] = StreamingOutput()
|
|
@@ -231,7 +250,7 @@ class WriteMixin:
|
|
|
231
250
|
streamed_response += chunk
|
|
232
251
|
# Only add the streaming symbol on the second text chunk
|
|
233
252
|
stream_container.markdown(
|
|
234
|
-
streamed_response + ("" if first_text else
|
|
253
|
+
streamed_response + ("" if first_text else cursor_str),
|
|
235
254
|
)
|
|
236
255
|
elif callable(chunk):
|
|
237
256
|
flush_stream_response()
|
|
@@ -254,7 +273,7 @@ class WriteMixin:
|
|
|
254
273
|
return written_content
|
|
255
274
|
|
|
256
275
|
@gather_metrics("write")
|
|
257
|
-
def write(self, *args: Any, unsafe_allow_html: bool = False
|
|
276
|
+
def write(self, *args: Any, unsafe_allow_html: bool = False) -> None:
|
|
258
277
|
"""Displays arguments in the app.
|
|
259
278
|
|
|
260
279
|
This is the Swiss Army knife of Streamlit commands: it does different
|
|
@@ -323,13 +342,6 @@ class WriteMixin:
|
|
|
323
342
|
If you only want to insert HTML or CSS without Markdown text,
|
|
324
343
|
we recommend using ``st.html`` instead.
|
|
325
344
|
|
|
326
|
-
**kwargs : any
|
|
327
|
-
Keyword arguments. Not used.
|
|
328
|
-
|
|
329
|
-
.. deprecated::
|
|
330
|
-
``**kwargs`` is deprecated and will be removed in a later version.
|
|
331
|
-
Use other, more specific Streamlit commands to pass additional
|
|
332
|
-
keyword arguments.
|
|
333
345
|
|
|
334
346
|
Returns
|
|
335
347
|
-------
|
|
@@ -400,13 +412,6 @@ class WriteMixin:
|
|
|
400
412
|
height: 300px
|
|
401
413
|
|
|
402
414
|
"""
|
|
403
|
-
if kwargs:
|
|
404
|
-
_LOGGER.warning(
|
|
405
|
-
'Invalid arguments were passed to "st.write" function. Support for '
|
|
406
|
-
"passing such unknown keywords arguments will be dropped in future. "
|
|
407
|
-
"Invalid arguments were: %s",
|
|
408
|
-
kwargs,
|
|
409
|
-
)
|
|
410
415
|
|
|
411
416
|
if len(args) == 1 and isinstance(args[0], str):
|
|
412
417
|
# Optimization: If there is only one arg, and it's a string,
|