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.
Files changed (259) hide show
  1. streamlit/__init__.py +4 -1
  2. streamlit/column_config.py +2 -0
  3. streamlit/commands/navigation.py +7 -7
  4. streamlit/commands/page_config.py +4 -6
  5. streamlit/components/v1/custom_component.py +17 -42
  6. streamlit/components/v2/__init__.py +458 -0
  7. streamlit/components/v2/bidi_component/__init__.py +20 -0
  8. streamlit/components/v2/bidi_component/constants.py +29 -0
  9. streamlit/components/v2/bidi_component/main.py +386 -0
  10. streamlit/components/v2/bidi_component/serialization.py +265 -0
  11. streamlit/components/v2/bidi_component/state.py +92 -0
  12. streamlit/components/v2/component_definition_resolver.py +143 -0
  13. streamlit/components/v2/component_file_watcher.py +403 -0
  14. streamlit/components/v2/component_manager.py +431 -0
  15. streamlit/components/v2/component_manifest_handler.py +122 -0
  16. streamlit/components/v2/component_path_utils.py +245 -0
  17. streamlit/components/v2/component_registry.py +409 -0
  18. streamlit/components/v2/get_bidi_component_manager.py +51 -0
  19. streamlit/components/v2/manifest_scanner.py +615 -0
  20. streamlit/components/v2/presentation.py +198 -0
  21. streamlit/components/v2/types.py +324 -0
  22. streamlit/config.py +741 -32
  23. streamlit/config_option.py +4 -1
  24. streamlit/config_util.py +650 -1
  25. streamlit/connections/base_connection.py +4 -2
  26. streamlit/dataframe_util.py +18 -10
  27. streamlit/delta_generator.py +8 -7
  28. streamlit/delta_generator_singletons.py +3 -1
  29. streamlit/deprecation_util.py +17 -6
  30. streamlit/elements/arrow.py +90 -42
  31. streamlit/elements/deck_gl_json_chart.py +98 -39
  32. streamlit/elements/dialog_decorator.py +2 -1
  33. streamlit/elements/exception.py +3 -1
  34. streamlit/elements/form.py +6 -6
  35. streamlit/elements/graphviz_chart.py +24 -9
  36. streamlit/elements/heading.py +3 -5
  37. streamlit/elements/iframe.py +0 -2
  38. streamlit/elements/image.py +12 -13
  39. streamlit/elements/layouts.py +89 -22
  40. streamlit/elements/lib/built_in_chart_utils.py +95 -31
  41. streamlit/elements/lib/color_util.py +8 -18
  42. streamlit/elements/lib/column_config_utils.py +9 -8
  43. streamlit/elements/lib/column_types.py +595 -148
  44. streamlit/elements/lib/dialog.py +3 -2
  45. streamlit/elements/lib/image_utils.py +3 -5
  46. streamlit/elements/lib/layout_utils.py +50 -13
  47. streamlit/elements/lib/mutable_status_container.py +2 -2
  48. streamlit/elements/lib/options_selector_utils.py +2 -2
  49. streamlit/elements/lib/pandas_styler_utils.py +30 -14
  50. streamlit/elements/lib/utils.py +21 -9
  51. streamlit/elements/map.py +81 -40
  52. streamlit/elements/media.py +7 -7
  53. streamlit/elements/metric.py +11 -35
  54. streamlit/elements/pdf.py +2 -4
  55. streamlit/elements/plotly_chart.py +142 -26
  56. streamlit/elements/progress.py +2 -4
  57. streamlit/elements/pyplot.py +6 -6
  58. streamlit/elements/space.py +113 -0
  59. streamlit/elements/vega_charts.py +400 -143
  60. streamlit/elements/widgets/audio_input.py +52 -4
  61. streamlit/elements/widgets/button.py +29 -29
  62. streamlit/elements/widgets/button_group.py +33 -6
  63. streamlit/elements/widgets/camera_input.py +3 -4
  64. streamlit/elements/widgets/chat.py +7 -0
  65. streamlit/elements/widgets/checkbox.py +1 -0
  66. streamlit/elements/widgets/color_picker.py +1 -0
  67. streamlit/elements/widgets/data_editor.py +34 -29
  68. streamlit/elements/widgets/file_uploader.py +6 -10
  69. streamlit/elements/widgets/multiselect.py +14 -3
  70. streamlit/elements/widgets/number_input.py +5 -4
  71. streamlit/elements/widgets/radio.py +10 -2
  72. streamlit/elements/widgets/select_slider.py +8 -4
  73. streamlit/elements/widgets/selectbox.py +9 -2
  74. streamlit/elements/widgets/slider.py +38 -41
  75. streamlit/elements/widgets/text_widgets.py +6 -0
  76. streamlit/elements/widgets/time_widgets.py +15 -12
  77. streamlit/elements/write.py +28 -23
  78. streamlit/emojis.py +1 -1
  79. streamlit/errors.py +115 -0
  80. streamlit/git_util.py +65 -43
  81. streamlit/hello/hello.py +8 -0
  82. streamlit/hello/utils.py +2 -1
  83. streamlit/material_icon_names.py +1 -1
  84. streamlit/navigation/page.py +4 -1
  85. streamlit/proto/ArrowData_pb2.py +27 -0
  86. streamlit/proto/ArrowData_pb2.pyi +46 -0
  87. streamlit/proto/Arrow_pb2.py +10 -8
  88. streamlit/proto/Arrow_pb2.pyi +31 -2
  89. streamlit/proto/AudioInput_pb2.py +2 -2
  90. streamlit/proto/AudioInput_pb2.pyi +6 -2
  91. streamlit/proto/BidiComponent_pb2.py +34 -0
  92. streamlit/proto/BidiComponent_pb2.pyi +153 -0
  93. streamlit/proto/Block_pb2.py +11 -11
  94. streamlit/proto/Block_pb2.pyi +9 -1
  95. streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
  96. streamlit/proto/DeckGlJsonChart_pb2.pyi +9 -3
  97. streamlit/proto/Element_pb2.py +5 -3
  98. streamlit/proto/Element_pb2.pyi +14 -4
  99. streamlit/proto/HeightConfig_pb2.py +2 -2
  100. streamlit/proto/HeightConfig_pb2.pyi +6 -3
  101. streamlit/proto/NewSession_pb2.py +18 -16
  102. streamlit/proto/NewSession_pb2.pyi +158 -6
  103. streamlit/proto/PlotlyChart_pb2.py +8 -6
  104. streamlit/proto/PlotlyChart_pb2.pyi +3 -1
  105. streamlit/proto/Space_pb2.py +27 -0
  106. streamlit/proto/Space_pb2.pyi +42 -0
  107. streamlit/proto/WidgetStates_pb2.py +2 -2
  108. streamlit/proto/WidgetStates_pb2.pyi +13 -3
  109. streamlit/proto/WidthConfig_pb2.py +2 -2
  110. streamlit/proto/WidthConfig_pb2.pyi +6 -3
  111. streamlit/runtime/app_session.py +45 -6
  112. streamlit/runtime/caching/cache_data_api.py +4 -4
  113. streamlit/runtime/caching/cache_errors.py +4 -1
  114. streamlit/runtime/caching/cache_resource_api.py +3 -2
  115. streamlit/runtime/caching/cache_utils.py +2 -1
  116. streamlit/runtime/caching/cached_message_replay.py +3 -3
  117. streamlit/runtime/caching/hashing.py +3 -4
  118. streamlit/runtime/caching/legacy_cache_api.py +2 -1
  119. streamlit/runtime/connection_factory.py +1 -3
  120. streamlit/runtime/forward_msg_queue.py +4 -1
  121. streamlit/runtime/fragment.py +2 -1
  122. streamlit/runtime/memory_media_file_storage.py +1 -1
  123. streamlit/runtime/metrics_util.py +6 -2
  124. streamlit/runtime/runtime.py +14 -0
  125. streamlit/runtime/scriptrunner/exec_code.py +2 -1
  126. streamlit/runtime/scriptrunner/script_runner.py +2 -2
  127. streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
  128. streamlit/runtime/secrets.py +2 -4
  129. streamlit/runtime/session_manager.py +3 -1
  130. streamlit/runtime/state/common.py +30 -5
  131. streamlit/runtime/state/presentation.py +85 -0
  132. streamlit/runtime/state/safe_session_state.py +2 -2
  133. streamlit/runtime/state/session_state.py +220 -16
  134. streamlit/runtime/state/widgets.py +19 -3
  135. streamlit/runtime/theme_util.py +148 -0
  136. streamlit/runtime/websocket_session_manager.py +3 -1
  137. streamlit/source_util.py +2 -2
  138. streamlit/static/index.html +2 -2
  139. streamlit/static/manifest.json +244 -227
  140. streamlit/static/static/css/{index.C8X8rNzw.css → index.BpABIXK9.css} +1 -1
  141. streamlit/static/static/css/index.DgR7E2CV.css +1 -0
  142. streamlit/static/static/js/{ErrorOutline.esm.DcGrhbBP.js → ErrorOutline.esm.YoJdlW1p.js} +1 -1
  143. streamlit/static/static/js/{FileDownload.esm.DgBvV6Pq.js → FileDownload.esm.Ddx8VEYy.js} +1 -1
  144. streamlit/static/static/js/{FileHelper.M6AAaeuA.js → FileHelper.90EtOmj9.js} +1 -1
  145. streamlit/static/static/js/{FormClearHelper.DHh1GFzm.js → FormClearHelper.BB1Km6eP.js} +1 -1
  146. streamlit/static/static/js/InputInstructions.jhH15PqV.js +1 -0
  147. streamlit/static/static/js/{Particles.DDVT-6Qc.js → Particles.DUsputn1.js} +1 -1
  148. streamlit/static/static/js/{ProgressBar.BEY0cXXV.js → ProgressBar.DLY8H6nE.js} +2 -2
  149. streamlit/static/static/js/Toolbar.D8nHCkuz.js +1 -0
  150. streamlit/static/static/js/{base-input.CK3UVGp1.js → base-input.CJGiNqed.js} +3 -3
  151. streamlit/static/static/js/{checkbox.D8W881TL.js → checkbox.Cpdd482O.js} +1 -1
  152. streamlit/static/static/js/{createSuper.B6W-Dh9S.js → createSuper.CuQIogbW.js} +1 -1
  153. streamlit/static/static/js/data-grid-overlay-editor.2Ufgxc6y.js +1 -0
  154. streamlit/static/static/js/{downloader.DiKpuU_S.js → downloader.CN0K7xlu.js} +1 -1
  155. streamlit/static/static/js/{es6.B8zRNPZ-.js → es6.BJcsVXQ0.js} +2 -2
  156. streamlit/static/static/js/{iframeResizer.contentWindow.DIewJmmh.js → iframeResizer.contentWindow.XzUvQqcZ.js} +1 -1
  157. streamlit/static/static/js/index.B1ZQh4P1.js +1 -0
  158. streamlit/static/static/js/index.BKstZk0M.js +27 -0
  159. streamlit/static/static/js/{index.Bte_9Lyq.js → index.BMcFsUee.js} +1 -1
  160. streamlit/static/static/js/{index.qhs54UAB.js → index.BR-IdcTb.js} +1 -1
  161. streamlit/static/static/js/{index.CejBxbg1.js → index.B_dWA3vd.js} +1 -1
  162. streamlit/static/static/js/{index.D5naqx-J.js → index.BgnZEMVh.js} +1 -1
  163. streamlit/static/static/js/{index.C7fRKRs4.js → index.BohqXifI.js} +1 -1
  164. streamlit/static/static/js/{index.cnnXF7xQ.js → index.Br5nxKNj.js} +1 -1
  165. streamlit/static/static/js/index.BrIKVbNc.js +3 -0
  166. streamlit/static/static/js/index.BtWUPzle.js +1 -0
  167. streamlit/static/static/js/index.C0RLraek.js +1 -0
  168. streamlit/static/static/js/{index.CP5TD2z1.js → index.CAIjskgG.js} +1 -1
  169. streamlit/static/static/js/{index.CD8HuT3N.js → index.CAj-7vWz.js} +135 -162
  170. streamlit/static/static/js/{index.DtYN2x4k.js → index.CMtEit2O.js} +1 -1
  171. streamlit/static/static/js/index.CkRlykEE.js +12 -0
  172. streamlit/static/static/js/{index.Ts_0SdB9.js → index.CmN3FXfI.js} +2 -2
  173. streamlit/static/static/js/{index.BnEpvLEz.js → index.CwbFI1_-.js} +1 -1
  174. streamlit/static/static/js/{index.CcJf6BCU.js → index.CxIUUfab.js} +27 -27
  175. streamlit/static/static/js/index.D2KPNy7e.js +1 -0
  176. streamlit/static/static/js/{index.Ch7MBCx0.js → index.D3GPA5k4.js} +47 -47
  177. streamlit/static/static/js/{index.ho6NIXGl.js → index.DGAh7DMq.js} +1 -1
  178. streamlit/static/static/js/index.DKb_NvmG.js +197 -0
  179. streamlit/static/static/js/{index.CvYYtxD_.js → index.DMqgUYKq.js} +1 -1
  180. streamlit/static/static/js/{index.zecpGxtj.js → index.DOFlg3dS.js} +1 -1
  181. streamlit/static/static/js/{index.B9mjBcgE.js → index.DPUXkcQL.js} +1 -1
  182. streamlit/static/static/js/index.DX1xY89g.js +1 -0
  183. streamlit/static/static/js/index.DYATBCsq.js +2 -0
  184. streamlit/static/static/js/{index.D2-atlaQ.js → index.DaSmGJ76.js} +3 -3
  185. streamlit/static/static/js/index.Dd7bMeLP.js +1 -0
  186. streamlit/static/static/js/{index.4eF4NxG2.js → index.DjmmgI5U.js} +1 -1
  187. streamlit/static/static/js/index.Dq56CyM2.js +1 -0
  188. streamlit/static/static/js/index.DuiXaS5_.js +7 -0
  189. streamlit/static/static/js/index.DvFidMLe.js +2 -0
  190. streamlit/static/static/js/{index.452cqrrL.js → index.DwkhC5Pc.js} +1 -1
  191. streamlit/static/static/js/{index.Dk4C7X3i.js → index.Q-3sFn1v.js} +1 -1
  192. streamlit/static/static/js/{index.CjXWwH-y.js → index.QJ5QO9sJ.js} +1 -1
  193. streamlit/static/static/js/{index.B6U8LQo3.js → index.VwTaeety.js} +1 -1
  194. streamlit/static/static/js/index.YOqQbeX8.js +1 -0
  195. streamlit/static/static/js/{input.nzVJphXi.js → input.D4MN_FzN.js} +1 -1
  196. streamlit/static/static/js/{memory.CjCgTQz3.js → memory.DrZjtdGT.js} +1 -1
  197. streamlit/static/static/js/{number-overlay-editor.DaRFzZEO.js → number-overlay-editor.DRwAw1In.js} +1 -1
  198. streamlit/static/static/js/{possibleConstructorReturn.DgiPnZ9N.js → possibleConstructorReturn.exeeJQEP.js} +1 -1
  199. streamlit/static/static/js/record.B-tDciZb.js +1 -0
  200. streamlit/static/static/js/{sandbox.mithfq7Z.js → sandbox.ClO3IuUr.js} +1 -1
  201. streamlit/static/static/js/{timepicker.Dbl5KFh6.js → timepicker.DAhu-vcF.js} +4 -4
  202. streamlit/static/static/js/{toConsumableArray.D-Dx88BQ.js → toConsumableArray.DNbljYEC.js} +1 -1
  203. streamlit/static/static/js/{uniqueId.Bh26R_3S.js → uniqueId.oG4Gvj1v.js} +1 -1
  204. streamlit/static/static/js/{useBasicWidgetState.DeK-QJpD.js → useBasicWidgetState.D6sOH6oI.js} +1 -1
  205. streamlit/static/static/js/{useTextInputAutoExpand.4iAdLWD-.js → useTextInputAutoExpand.4u3_GcuN.js} +2 -2
  206. streamlit/static/static/js/{useUpdateUiValue.CmT7_nJN.js → useUpdateUiValue.F2R3eTeR.js} +1 -1
  207. streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
  208. streamlit/static/static/js/withFullScreenWrapper.zothJIsI.js +1 -0
  209. streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
  210. streamlit/string_util.py +56 -1
  211. streamlit/testing/v1/app_test.py +2 -2
  212. streamlit/testing/v1/element_tree.py +23 -9
  213. streamlit/testing/v1/util.py +2 -2
  214. streamlit/type_util.py +3 -4
  215. streamlit/url_util.py +1 -3
  216. streamlit/user_info.py +1 -2
  217. streamlit/util.py +3 -1
  218. streamlit/watcher/event_based_path_watcher.py +23 -12
  219. streamlit/watcher/local_sources_watcher.py +11 -1
  220. streamlit/watcher/path_watcher.py +9 -6
  221. streamlit/watcher/polling_path_watcher.py +4 -1
  222. streamlit/watcher/util.py +2 -2
  223. streamlit/web/bootstrap.py +0 -31
  224. streamlit/web/cli.py +51 -22
  225. streamlit/web/server/bidi_component_request_handler.py +193 -0
  226. streamlit/web/server/component_file_utils.py +97 -0
  227. streamlit/web/server/component_request_handler.py +8 -21
  228. streamlit/web/server/oidc_mixin.py +3 -1
  229. streamlit/web/server/routes.py +18 -5
  230. streamlit/web/server/server.py +10 -0
  231. streamlit/web/server/server_util.py +3 -1
  232. streamlit/web/server/upload_file_request_handler.py +3 -1
  233. {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/METADATA +4 -5
  234. {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/RECORD +238 -209
  235. streamlit/static/static/css/index.COe1010n.css +0 -1
  236. streamlit/static/static/js/Hooks.DGu1od_L.js +0 -1
  237. streamlit/static/static/js/InputInstructions.z6sVgyYt.js +0 -1
  238. streamlit/static/static/js/Toolbar.DSnK1fUh.js +0 -1
  239. streamlit/static/static/js/data-grid-overlay-editor.DRTHOydk.js +0 -1
  240. streamlit/static/static/js/index.BXYmrqnf.js +0 -1
  241. streamlit/static/static/js/index.B_8AnktO.js +0 -1
  242. streamlit/static/static/js/index.Bl7zGQSh.js +0 -7
  243. streamlit/static/static/js/index.BnJIOYn9.js +0 -73
  244. streamlit/static/static/js/index.C1HcTl5K.js +0 -1
  245. streamlit/static/static/js/index.C7lSmSOP.js +0 -1
  246. streamlit/static/static/js/index.C_tmcx4B.js +0 -1
  247. streamlit/static/static/js/index.D3K5nOu9.js +0 -197
  248. streamlit/static/static/js/index.DkKT3LUI.js +0 -1
  249. streamlit/static/static/js/index.MTPPBDHk.js +0 -2
  250. streamlit/static/static/js/index.pqW9AMJD.js +0 -3
  251. streamlit/static/static/js/index.urHgTgMQ.js +0 -12
  252. streamlit/static/static/js/index.wzkv_11M.js +0 -1
  253. streamlit/static/static/js/index.yF5AncHY.js +0 -1
  254. streamlit/static/static/js/withFullScreenWrapper.DLp1ENGm.js +0 -1
  255. streamlit/static/static/media/MaterialSymbols-Rounded.CBxVaFdk.woff2 +0 -0
  256. {streamlit-1.49.1.data → streamlit-1.51.0.data}/scripts/streamlit.cmd +0 -0
  257. {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/WHEEL +0 -0
  258. {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/entry_points.txt +0 -0
  259. {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/top_level.txt +0 -0
@@ -16,9 +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, Union, cast
20
-
21
- from typing_extensions import TypeAlias
19
+ from typing import TYPE_CHECKING, TypeAlias, cast
22
20
 
23
21
  from streamlit.elements.lib.file_uploader_utils import enforce_filename_restriction
24
22
  from streamlit.elements.lib.form_utils import current_form_id
@@ -35,6 +33,7 @@ from streamlit.elements.lib.utils import (
35
33
  to_key,
36
34
  )
37
35
  from streamlit.elements.widgets.file_uploader import _get_upload_files
36
+ from streamlit.errors import StreamlitAPIException
38
37
  from streamlit.proto.AudioInput_pb2 import AudioInput as AudioInputProto
39
38
  from streamlit.proto.Common_pb2 import FileUploaderState as FileUploaderStateProto
40
39
  from streamlit.proto.Common_pb2 import UploadedFileInfo as UploadedFileInfoProto
@@ -52,7 +51,10 @@ if TYPE_CHECKING:
52
51
  from streamlit.delta_generator import DeltaGenerator
53
52
  from streamlit.elements.lib.layout_utils import WidthWithoutContent
54
53
 
55
- SomeUploadedAudioFile: TypeAlias = Union[UploadedFile, DeletedFile, None]
54
+ SomeUploadedAudioFile: TypeAlias = UploadedFile | DeletedFile | None
55
+
56
+ # Allowed sample rates for audio recording
57
+ ALLOWED_SAMPLE_RATES = {8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000}
56
58
 
57
59
 
58
60
  @dataclass
@@ -90,6 +92,7 @@ class AudioInputMixin:
90
92
  self,
91
93
  label: str,
92
94
  *,
95
+ sample_rate: int | None = 16000,
93
96
  key: Key | None = None,
94
97
  help: str | None = None,
95
98
  on_change: WidgetCallback | None = None,
@@ -125,6 +128,15 @@ class AudioInputMixin:
125
128
  .. |st.markdown| replace:: ``st.markdown``
126
129
  .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
127
130
 
131
+ sample_rate : int or None
132
+ The target sample rate for the audio recording in Hz.
133
+ This defaults to 16000 Hz, which is optimal for speech recognition.
134
+
135
+ The following sample rates are supported: 8000, 11025, 16000,
136
+ 22050, 24000, 32000, 44100, or 48000. If this is ``None``, the
137
+ widget uses the browser's default sample rate (typically 44100 or
138
+ 48000 Hz).
139
+
128
140
  key : str or int
129
141
  An optional string or integer to use as the unique key for the widget.
130
142
  If this is omitted, a key will be generated for the widget
@@ -185,6 +197,10 @@ class AudioInputMixin:
185
197
 
186
198
  Examples
187
199
  --------
200
+ *Example 1:* Record a voice message and play it back.*
201
+
202
+ The default sample rate of 16000 Hz is optimal for speech recognition.
203
+
188
204
  >>> import streamlit as st
189
205
  >>>
190
206
  >>> audio_value = st.audio_input("Record a voice message")
@@ -196,10 +212,34 @@ class AudioInputMixin:
196
212
  https://doc-audio-input.streamlit.app/
197
213
  height: 260px
198
214
 
215
+ *Example 2:* Record high-fidelity audio and play it back.*
216
+
217
+ Higher sample rates can create higher-quality, larger audio files. This
218
+ might require a nicer microphone to fully appreciate the difference.
219
+
220
+ >>> import streamlit as st
221
+ >>>
222
+ >>> audio_value = st.audio_input("Record high quality audio", sample_rate=48000)
223
+ >>>
224
+ >>> if audio_value:
225
+ ... st.audio(audio_value)
226
+
227
+ .. output::
228
+ https://doc-audio-input-high-rate.streamlit.app/
229
+ height: 260px
230
+
199
231
  """
232
+ # Validate sample_rate parameter
233
+ if sample_rate is not None and sample_rate not in ALLOWED_SAMPLE_RATES:
234
+ raise StreamlitAPIException(
235
+ f"Invalid sample_rate: {sample_rate}. "
236
+ f"Must be one of {sorted(ALLOWED_SAMPLE_RATES)} Hz, or None for browser default."
237
+ )
238
+
200
239
  ctx = get_script_run_ctx()
201
240
  return self._audio_input(
202
241
  label=label,
242
+ sample_rate=sample_rate,
203
243
  key=key,
204
244
  help=help,
205
245
  on_change=on_change,
@@ -214,6 +254,7 @@ class AudioInputMixin:
214
254
  def _audio_input(
215
255
  self,
216
256
  label: str,
257
+ sample_rate: int | None = 16000,
217
258
  key: Key | None = None,
218
259
  help: str | None = None,
219
260
  on_change: WidgetCallback | None = None,
@@ -239,10 +280,13 @@ class AudioInputMixin:
239
280
  element_id = compute_and_register_element_id(
240
281
  "audio_input",
241
282
  user_key=key,
283
+ # Treat the provided key as the main identity.
284
+ key_as_main_identity=True,
242
285
  dg=self.dg,
243
286
  label=label,
244
287
  help=help,
245
288
  width=width,
289
+ sample_rate=sample_rate,
246
290
  )
247
291
 
248
292
  audio_input_proto = AudioInputProto()
@@ -254,6 +298,10 @@ class AudioInputMixin:
254
298
  label_visibility
255
299
  )
256
300
 
301
+ # Set sample_rate in protobuf if specified
302
+ if sample_rate is not None:
303
+ audio_input_proto.sample_rate = sample_rate
304
+
257
305
  if label and help is not None:
258
306
  audio_input_proto.help = dedent(help)
259
307
 
@@ -25,12 +25,10 @@ from typing import (
25
25
  Final,
26
26
  Literal,
27
27
  TextIO,
28
- Union,
28
+ TypeAlias,
29
29
  cast,
30
30
  )
31
31
 
32
- from typing_extensions import TypeAlias
33
-
34
32
  from streamlit import runtime
35
33
  from streamlit.elements.lib.form_utils import current_form_id, is_in_form
36
34
  from streamlit.elements.lib.layout_utils import LayoutConfig, Width, validate_width
@@ -74,7 +72,7 @@ For more information, refer to the
74
72
  [documentation for forms](https://docs.streamlit.io/develop/api-reference/execution-flow/st.form).
75
73
  """
76
74
 
77
- DownloadButtonDataType: TypeAlias = Union[str, bytes, TextIO, BinaryIO, io.RawIOBase]
75
+ DownloadButtonDataType: TypeAlias = str | bytes | TextIO | BinaryIO | io.RawIOBase
78
76
 
79
77
 
80
78
  @dataclass
@@ -188,6 +186,12 @@ class ButtonMixin:
188
186
  In both cases, if the contents of the button are wider than the
189
187
  parent container, the contents will line wrap.
190
188
 
189
+ .. deprecated::
190
+ ``use_container_width`` is deprecated and will be removed in a
191
+ future release. For ``use_container_width=True``, use
192
+ ``width="stretch"``. For ``use_container_width=False``, use
193
+ ``width="content"``.
194
+
191
195
  width : "content", "stretch", or int
192
196
  The width of the button. This can be one of the following:
193
197
 
@@ -201,12 +205,6 @@ class ButtonMixin:
201
205
  the parent container, the width of the button matches the width
202
206
  of the parent container.
203
207
 
204
- .. deprecated::
205
- ``use_container_width`` is deprecated and will be removed in a
206
- future release. For ``use_container_width=True``, use
207
- ``width="stretch"``. For ``use_container_width=False``, use
208
- ``width="content"``.
209
-
210
208
  Returns
211
209
  -------
212
210
  bool
@@ -432,6 +430,12 @@ class ButtonMixin:
432
430
  In both cases, if the contents of the button are wider than the
433
431
  parent container, the contents will line wrap.
434
432
 
433
+ .. deprecated::
434
+ ``use_container_width`` is deprecated and will be removed in a
435
+ future release. For ``use_container_width=True``, use
436
+ ``width="stretch"``. For ``use_container_width=False``, use
437
+ ``width="content"``.
438
+
435
439
  width : "content", "stretch", or int
436
440
  The width of the download button. This can be one of the following:
437
441
 
@@ -445,12 +449,6 @@ class ButtonMixin:
445
449
  the parent container, the width of the button matches the width
446
450
  of the parent container.
447
451
 
448
- .. deprecated::
449
- ``use_container_width`` is deprecated and will be removed in a
450
- future release. For ``use_container_width=True``, use
451
- ``width="stretch"``. For ``use_container_width=False``, use
452
- ``width="content"``.
453
-
454
452
  Returns
455
453
  -------
456
454
  bool
@@ -680,6 +678,12 @@ class ButtonMixin:
680
678
  In both cases, if the contents of the button are wider than the
681
679
  parent container, the contents will line wrap.
682
680
 
681
+ .. deprecated::
682
+ ``use_container_width`` is deprecated and will be removed in a
683
+ future release. For ``use_container_width=True``, use
684
+ ``width="stretch"``. For ``use_container_width=False``, use
685
+ ``width="content"``.
686
+
683
687
  width : "content", "stretch", or int
684
688
  The width of the link button. This can be one of the following:
685
689
 
@@ -693,12 +697,6 @@ class ButtonMixin:
693
697
  the parent container, the width of the button matches the width
694
698
  of the parent container.
695
699
 
696
- .. deprecated::
697
- ``use_container_width`` is deprecated and will be removed in a
698
- future release. For ``use_container_width=True``, use
699
- ``width="stretch"``. For ``use_container_width=False``, use
700
- ``width="content"``.
701
-
702
700
  Example
703
701
  -------
704
702
  >>> import streamlit as st
@@ -812,6 +810,12 @@ class ButtonMixin:
812
810
  The default is ``True`` for page links in the sidebar and ``False``
813
811
  for those in the main app.
814
812
 
813
+ .. deprecated::
814
+ ``use_container_width`` is deprecated and will be removed in a
815
+ future release. For ``use_container_width=True``, use
816
+ ``width="stretch"``. For ``use_container_width=False``, use
817
+ ``width="content"``.
818
+
815
819
  width : "content", "stretch", or int
816
820
  The width of the page-link button. This can be one of the following:
817
821
 
@@ -825,12 +829,6 @@ class ButtonMixin:
825
829
  the parent container, the width of the button matches the width
826
830
  of the parent container.
827
831
 
828
- .. deprecated::
829
- ``use_container_width`` is deprecated and will be removed in a
830
- future release. For ``use_container_width=True``, use
831
- ``width="stretch"``. For ``use_container_width=False``, use
832
- ``width="content"``.
833
-
834
832
  Example
835
833
  -------
836
834
  Consider the following example given this file structure:
@@ -914,6 +912,7 @@ class ButtonMixin:
914
912
  element_id = compute_and_register_element_id(
915
913
  "download_button",
916
914
  user_key=key,
915
+ key_as_main_identity=True,
917
916
  dg=self.dg,
918
917
  label=label,
919
918
  icon=icon,
@@ -1119,8 +1118,9 @@ class ButtonMixin:
1119
1118
  # Only the form submitter button needs a form ID at the moment.
1120
1119
  form_id = current_form_id(self.dg) if is_form_submitter else ""
1121
1120
  element_id = compute_and_register_element_id(
1122
- "button",
1121
+ "form_submit_button" if is_form_submitter else "button",
1123
1122
  user_key=key,
1123
+ key_as_main_identity=True,
1124
1124
  dg=self.dg,
1125
1125
  label=label,
1126
1126
  icon=icon,
@@ -14,22 +14,20 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from collections.abc import Sequence
17
+ from collections.abc import Callable, Sequence
18
18
  from dataclasses import dataclass, field
19
19
  from typing import (
20
20
  TYPE_CHECKING,
21
21
  Any,
22
- Callable,
23
22
  Final,
24
23
  Generic,
25
24
  Literal,
25
+ TypeAlias,
26
26
  TypeVar,
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,
@@ -276,6 +274,7 @@ class ButtonGroupMixin:
276
274
  options: Literal["thumbs"] = ...,
277
275
  *,
278
276
  key: Key | None = None,
277
+ default: int | None = None,
279
278
  disabled: bool = False,
280
279
  on_change: WidgetCallback | None = None,
281
280
  args: WidgetArgs | None = None,
@@ -288,6 +287,7 @@ class ButtonGroupMixin:
288
287
  options: Literal["faces", "stars"] = ...,
289
288
  *,
290
289
  key: Key | None = None,
290
+ default: int | None = None,
291
291
  disabled: bool = False,
292
292
  on_change: WidgetCallback | None = None,
293
293
  args: WidgetArgs | None = None,
@@ -300,6 +300,7 @@ class ButtonGroupMixin:
300
300
  options: Literal["thumbs", "faces", "stars"] = "thumbs",
301
301
  *,
302
302
  key: Key | None = None,
303
+ default: int | None = None,
303
304
  disabled: bool = False,
304
305
  on_change: WidgetCallback | None = None,
305
306
  args: WidgetArgs | None = None,
@@ -331,6 +332,14 @@ class ButtonGroupMixin:
331
332
  If this is omitted, a key will be generated for the widget
332
333
  based on its content. No two widgets may have the same key.
333
334
 
335
+ default : int or None
336
+ Default feedback value. This must be consistent with the feedback
337
+ type in ``options``:
338
+
339
+ - 0 or 1 if ``options="thumbs"``.
340
+ - Between 0 and 4, inclusive, if ``options="faces"`` or
341
+ ``options="stars"``.
342
+
334
343
  disabled : bool
335
344
  An optional boolean that disables the feedback widget if set
336
345
  to ``True``. The default is ``False``.
@@ -407,7 +416,17 @@ class ButtonGroupMixin:
407
416
  f"The argument passed was '{options}'."
408
417
  )
409
418
  transformed_options, options_indices = get_mapped_options(options)
410
- serde = _SingleSelectSerde[int](options_indices)
419
+
420
+ if default is not None and (default < 0 or default >= len(transformed_options)):
421
+ raise StreamlitAPIException(
422
+ f"The default value in '{options}' must be a number between 0 and {len(transformed_options) - 1}."
423
+ f" The passed default value is {default}"
424
+ )
425
+
426
+ _default: list[int] | None = (
427
+ [options_indices[default]] if default is not None else None
428
+ )
429
+ serde = _SingleSelectSerde[int](options_indices, default_value=_default)
411
430
 
412
431
  selection_visualization = ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
413
432
  if options == "stars":
@@ -417,7 +436,7 @@ class ButtonGroupMixin:
417
436
 
418
437
  sentiment = self._button_group(
419
438
  transformed_options,
420
- default=None,
439
+ default=_default,
421
440
  key=key,
422
441
  selection_mode="single",
423
442
  disabled=disabled,
@@ -597,6 +616,8 @@ class ButtonGroupMixin:
597
616
  options or an empty list. If the ``selection_mode`` is
598
617
  ``"single"``, this is a selected option or ``None``.
599
618
 
619
+ This contains copies of the selected options, not the originals.
620
+
600
621
  Examples
601
622
  --------
602
623
  **Example 1: Multi-select pills**
@@ -824,6 +845,8 @@ class ButtonGroupMixin:
824
845
  options or an empty list. If the ``selection_mode`` is
825
846
  ``"single"``, this is a selected option or ``None``.
826
847
 
848
+ This contains copies of the selected options, not the originals.
849
+
827
850
  Examples
828
851
  --------
829
852
  **Example 1: Multi-select segmented control**
@@ -1047,6 +1070,10 @@ class ButtonGroupMixin:
1047
1070
  # "feedback" in errors
1048
1071
  "feedback" if style == "borderless" else style,
1049
1072
  user_key=key,
1073
+ # Treat the provided key as the main identity for segmented_control, pills and feedback,
1074
+ # and only include kwargs that can invalidate the current selection.
1075
+ # We whitelist the formatted options and the click mode (single vs multi).
1076
+ key_as_main_identity={"options", "click_mode"},
1050
1077
  dg=self.dg,
1051
1078
  options=formatted_options,
1052
1079
  default=default,
@@ -16,9 +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, Union, cast
20
-
21
- from typing_extensions import TypeAlias
19
+ from typing import TYPE_CHECKING, TypeAlias, cast
22
20
 
23
21
  from streamlit.elements.lib.file_uploader_utils import enforce_filename_restriction
24
22
  from streamlit.elements.lib.form_utils import current_form_id
@@ -52,7 +50,7 @@ if TYPE_CHECKING:
52
50
  from streamlit.delta_generator import DeltaGenerator
53
51
  from streamlit.elements.lib.layout_utils import WidthWithoutContent
54
52
 
55
- SomeUploadedSnapshotFile: TypeAlias = Union[UploadedFile, DeletedFile, None]
53
+ SomeUploadedSnapshotFile: TypeAlias = UploadedFile | DeletedFile | None
56
54
 
57
55
 
58
56
  @dataclass
@@ -234,6 +232,7 @@ class CameraInputMixin:
234
232
  element_id = compute_and_register_element_id(
235
233
  "camera_input",
236
234
  user_key=key,
235
+ key_as_main_identity=False,
237
236
  dg=self.dg,
238
237
  label=label,
239
238
  help=help,
@@ -624,6 +624,13 @@ class ChatMixin:
624
624
  element_id = compute_and_register_element_id(
625
625
  "chat_input",
626
626
  user_key=key,
627
+ # Treat the provided key as the main identity. Only include
628
+ # properties that can invalidate the current widget state
629
+ # when changed. For chat_input, those are:
630
+ # - accept_file: Changes whether files can be attached (and how)
631
+ # - file_type: Restricts the accepted file types
632
+ # - max_chars: Changes the maximum allowed characters for the input
633
+ key_as_main_identity={"accept_file", "file_type", "max_chars"},
627
634
  dg=self.dg,
628
635
  placeholder=placeholder,
629
636
  max_chars=max_chars,
@@ -342,6 +342,7 @@ class CheckboxMixin:
342
342
  element_id = compute_and_register_element_id(
343
343
  "toggle" if type == CheckboxProto.StyleType.TOGGLE else "checkbox",
344
344
  user_key=key,
345
+ key_as_main_identity=True,
345
346
  dg=self.dg,
346
347
  label=label,
347
348
  value=bool(value),
@@ -219,6 +219,7 @@ class ColorPickerMixin:
219
219
  element_id = compute_and_register_element_id(
220
220
  "color_picker",
221
221
  user_key=key,
222
+ key_as_main_identity=True,
222
223
  dg=self.dg,
223
224
  label=label,
224
225
  value=str(value),
@@ -22,6 +22,7 @@ from typing import (
22
22
  Any,
23
23
  Final,
24
24
  Literal,
25
+ TypeAlias,
25
26
  TypedDict,
26
27
  TypeVar,
27
28
  Union,
@@ -29,8 +30,6 @@ from typing import (
29
30
  overload,
30
31
  )
31
32
 
32
- from typing_extensions import TypeAlias
33
-
34
33
  from streamlit import dataframe_util
35
34
  from streamlit import logger as _logger
36
35
  from streamlit.deprecation_util import (
@@ -52,6 +51,7 @@ from streamlit.elements.lib.column_config_utils import (
52
51
  )
53
52
  from streamlit.elements.lib.form_utils import current_form_id
54
53
  from streamlit.elements.lib.layout_utils import (
54
+ HeightWithoutContent,
55
55
  LayoutConfig,
56
56
  Width,
57
57
  validate_height,
@@ -89,18 +89,11 @@ _LOGGER: Final = _logger.get_logger(__name__)
89
89
  # formats will be returned with the same type when used with data_editor.
90
90
  EditableData = TypeVar(
91
91
  "EditableData",
92
- bound=Union[
93
- dataframe_util.DataFrameGenericAlias[Any], # covers DataFrame and Series
94
- tuple[Any],
95
- list[Any],
96
- set[Any],
97
- dict[str, Any],
98
- # TODO(lukasmasuch): Add support for np.ndarray
99
- # but it is not possible with np.ndarray.
100
- # NDArray[Any] works, but is only available in numpy>1.20.
101
- # TODO(lukasmasuch): Add support for pa.Table typing
102
- # pa.Table does not work since it is a C-based class resulting in Any
103
- ],
92
+ bound=dataframe_util.DataFrameGenericAlias[Any]
93
+ | tuple[Any]
94
+ | list[Any]
95
+ | set[Any]
96
+ | dict[str, Any],
104
97
  )
105
98
 
106
99
 
@@ -171,7 +164,8 @@ class DataEditorSerde:
171
164
  # Convert the keys (numerical row positions) to integers.
172
165
  # The keys are strings because they are serialized to JSON.
173
166
  data_editor_state["edited_rows"] = {
174
- int(k): v for k, v in data_editor_state["edited_rows"].items()
167
+ int(k): v
168
+ for k, v in data_editor_state["edited_rows"].items() # ty: ignore[possibly-missing-attribute]
175
169
  }
176
170
  return data_editor_state
177
171
 
@@ -241,7 +235,7 @@ def _parse_value(
241
235
  ColumnDataKind.DATE,
242
236
  ColumnDataKind.TIME,
243
237
  ]:
244
- datetime_value = pd.Timestamp(value)
238
+ datetime_value = pd.Timestamp(value) # ty: ignore
245
239
 
246
240
  if datetime_value is pd.NaT:
247
241
  return None
@@ -602,7 +596,7 @@ class DataEditorMixin:
602
596
  data: EditableData,
603
597
  *,
604
598
  width: Width = "stretch",
605
- height: int | Literal["auto"] = "auto",
599
+ height: HeightWithoutContent | Literal["auto"] = "auto",
606
600
  use_container_width: bool | None = None,
607
601
  hide_index: bool | None = None,
608
602
  column_order: Iterable[str] | None = None,
@@ -623,7 +617,7 @@ class DataEditorMixin:
623
617
  data: Any,
624
618
  *,
625
619
  width: Width = "stretch",
626
- height: int | Literal["auto"] = "auto",
620
+ height: HeightWithoutContent | Literal["auto"] = "auto",
627
621
  use_container_width: bool | None = None,
628
622
  hide_index: bool | None = None,
629
623
  column_order: Iterable[str] | None = None,
@@ -644,7 +638,7 @@ class DataEditorMixin:
644
638
  data: DataTypes,
645
639
  *,
646
640
  width: Width = "stretch",
647
- height: int | Literal["auto"] = "auto",
641
+ height: HeightWithoutContent | Literal["auto"] = "auto",
648
642
  use_container_width: bool | None = None,
649
643
  hide_index: bool | None = None,
650
644
  column_order: Iterable[str] | None = None,
@@ -670,6 +664,9 @@ class DataEditorMixin:
670
664
  - Styles from ``pandas.Styler`` will only be applied to non-editable columns.
671
665
  - Text and number formatting from ``column_config`` always takes
672
666
  precedence over text and number formatting from ``pandas.Styler``.
667
+ - If your dataframe starts with an empty column, you should set
668
+ the column datatype in the underlying dataframe to ensure your
669
+ intended datatype, especially for integers versus floats.
673
670
  - Mixing data types within a column can make the column uneditable.
674
671
  - Additionally, the following data types are not yet supported for editing:
675
672
  ``complex``, ``tuple``, ``bytes``, ``bytearray``,
@@ -693,16 +690,23 @@ class DataEditorMixin:
693
690
  the parent container, the width of the editor matches the width
694
691
  of the parent container.
695
692
 
696
- height : int or "auto"
697
- The height of the data editor. This can be one of the following:
693
+ height : int, "auto", or "stretch"
694
+ The height of the editor. This can be one of the following:
698
695
 
699
696
  - ``"auto"`` (default): Streamlit sets the height to show at most
700
697
  ten rows.
698
+ - ``"stretch"``: The height of the editor expands to fill the
699
+ available vertical space in its parent container. When multiple
700
+ elements with stretch height are in the same container, they
701
+ share the available vertical space evenly. The editor will
702
+ maintain a minimum height to display up to three rows, but
703
+ otherwise won't exceed the available height in its parent
704
+ container.
701
705
  - An integer specifying the height in pixels: The editor has a
702
706
  fixed height.
703
707
 
704
- Vertical scrolling within the data editor is enabled when the
705
- height does not accommodate all rows.
708
+ Vertical scrolling within the editor is enabled when the height
709
+ does not accommodate all rows.
706
710
 
707
711
  use_container_width : bool
708
712
  Whether to override ``width`` with the width of the parent
@@ -711,6 +715,11 @@ class DataEditorMixin:
711
715
  this is ``False``, Streamlit sets the data editor's width according
712
716
  to ``width``.
713
717
 
718
+ .. deprecated::
719
+ ``use_container_width`` is deprecated and will be removed in a
720
+ future release. For ``use_container_width=True``, use
721
+ ``width="stretch"``.
722
+
714
723
  hide_index : bool or None
715
724
  Whether to hide the index column(s). If ``hide_index`` is ``None``
716
725
  (default), the visibility of index columns is automatically
@@ -793,11 +802,6 @@ class DataEditorMixin:
793
802
  is ``None`` (default), Streamlit will use a default row height,
794
803
  which fits one line of text.
795
804
 
796
- .. deprecated::
797
- ``use_container_width`` is deprecated and will be removed in a
798
- future release. For ``use_container_width=True``, use
799
- ``width="stretch"``.
800
-
801
805
  Returns
802
806
  -------
803
807
  pandas.DataFrame, pandas.Series, pyarrow.Table, numpy.ndarray, list, set, tuple, or dict.
@@ -904,7 +908,7 @@ class DataEditorMixin:
904
908
  validate_height(
905
909
  height,
906
910
  allow_content=False,
907
- allow_stretch=False,
911
+ allow_stretch=True,
908
912
  additional_allowed=["auto"],
909
913
  )
910
914
 
@@ -1028,6 +1032,7 @@ class DataEditorMixin:
1028
1032
  element_id = compute_and_register_element_id(
1029
1033
  "data_editor",
1030
1034
  user_key=key,
1035
+ key_as_main_identity=False,
1031
1036
  dg=self.dg,
1032
1037
  data=arrow_bytes,
1033
1038
  width=width,
@@ -16,9 +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, Literal, Union, cast, overload
20
-
21
- from typing_extensions import TypeAlias
19
+ from typing import TYPE_CHECKING, Literal, TypeAlias, cast, overload
22
20
 
23
21
  from streamlit import config
24
22
  from streamlit.elements.lib.file_uploader_utils import (
@@ -60,18 +58,15 @@ if TYPE_CHECKING:
60
58
 
61
59
  from streamlit.delta_generator import DeltaGenerator
62
60
 
63
- SomeUploadedFiles: TypeAlias = Union[
64
- UploadedFile,
65
- DeletedFile,
66
- list[Union[UploadedFile, DeletedFile]],
67
- None,
68
- ]
61
+ SomeUploadedFiles: TypeAlias = (
62
+ UploadedFile | DeletedFile | list[UploadedFile | DeletedFile] | None
63
+ )
69
64
 
70
65
  # Type alias for accept_multiple_files parameter.
71
66
  # If True, multiple files can be uploaded.
72
67
  # If False, only a single file can be uploaded.
73
68
  # If set to the literal "directory", users can upload an entire directory (folder) of files.
74
- AcceptMultipleFiles: TypeAlias = Union[bool, Literal["directory"]]
69
+ AcceptMultipleFiles: TypeAlias = bool | Literal["directory"]
75
70
 
76
71
 
77
72
  def _get_upload_files(
@@ -488,6 +483,7 @@ class FileUploaderMixin:
488
483
  element_id = compute_and_register_element_id(
489
484
  "file_uploader",
490
485
  user_key=key,
486
+ key_as_main_identity=False,
491
487
  dg=self.dg,
492
488
  label=label,
493
489
  type=type,