streamlit 1.50.0__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 (232) hide show
  1. streamlit/__init__.py +4 -1
  2. streamlit/commands/navigation.py +4 -6
  3. streamlit/commands/page_config.py +4 -6
  4. streamlit/components/v2/__init__.py +458 -0
  5. streamlit/components/v2/bidi_component/__init__.py +20 -0
  6. streamlit/components/v2/bidi_component/constants.py +29 -0
  7. streamlit/components/v2/bidi_component/main.py +386 -0
  8. streamlit/components/v2/bidi_component/serialization.py +265 -0
  9. streamlit/components/v2/bidi_component/state.py +92 -0
  10. streamlit/components/v2/component_definition_resolver.py +143 -0
  11. streamlit/components/v2/component_file_watcher.py +403 -0
  12. streamlit/components/v2/component_manager.py +431 -0
  13. streamlit/components/v2/component_manifest_handler.py +122 -0
  14. streamlit/components/v2/component_path_utils.py +245 -0
  15. streamlit/components/v2/component_registry.py +409 -0
  16. streamlit/components/v2/get_bidi_component_manager.py +51 -0
  17. streamlit/components/v2/manifest_scanner.py +615 -0
  18. streamlit/components/v2/presentation.py +198 -0
  19. streamlit/components/v2/types.py +324 -0
  20. streamlit/config.py +456 -53
  21. streamlit/config_option.py +4 -1
  22. streamlit/config_util.py +650 -1
  23. streamlit/dataframe_util.py +15 -8
  24. streamlit/delta_generator.py +6 -4
  25. streamlit/delta_generator_singletons.py +3 -1
  26. streamlit/deprecation_util.py +17 -6
  27. streamlit/elements/arrow.py +37 -9
  28. streamlit/elements/deck_gl_json_chart.py +97 -39
  29. streamlit/elements/dialog_decorator.py +2 -1
  30. streamlit/elements/exception.py +3 -1
  31. streamlit/elements/graphviz_chart.py +1 -3
  32. streamlit/elements/heading.py +3 -5
  33. streamlit/elements/image.py +2 -4
  34. streamlit/elements/layouts.py +31 -11
  35. streamlit/elements/lib/built_in_chart_utils.py +1 -3
  36. streamlit/elements/lib/color_util.py +8 -18
  37. streamlit/elements/lib/column_config_utils.py +4 -8
  38. streamlit/elements/lib/column_types.py +40 -12
  39. streamlit/elements/lib/dialog.py +2 -2
  40. streamlit/elements/lib/image_utils.py +3 -5
  41. streamlit/elements/lib/layout_utils.py +50 -13
  42. streamlit/elements/lib/mutable_status_container.py +2 -2
  43. streamlit/elements/lib/options_selector_utils.py +2 -2
  44. streamlit/elements/lib/utils.py +4 -4
  45. streamlit/elements/map.py +80 -37
  46. streamlit/elements/media.py +5 -7
  47. streamlit/elements/metric.py +3 -5
  48. streamlit/elements/pdf.py +2 -4
  49. streamlit/elements/plotly_chart.py +125 -17
  50. streamlit/elements/progress.py +2 -4
  51. streamlit/elements/space.py +113 -0
  52. streamlit/elements/vega_charts.py +339 -148
  53. streamlit/elements/widgets/audio_input.py +5 -5
  54. streamlit/elements/widgets/button.py +2 -4
  55. streamlit/elements/widgets/button_group.py +33 -7
  56. streamlit/elements/widgets/camera_input.py +2 -4
  57. streamlit/elements/widgets/chat.py +7 -1
  58. streamlit/elements/widgets/color_picker.py +1 -1
  59. streamlit/elements/widgets/data_editor.py +28 -24
  60. streamlit/elements/widgets/file_uploader.py +5 -10
  61. streamlit/elements/widgets/multiselect.py +4 -3
  62. streamlit/elements/widgets/number_input.py +2 -4
  63. streamlit/elements/widgets/radio.py +10 -3
  64. streamlit/elements/widgets/select_slider.py +8 -5
  65. streamlit/elements/widgets/selectbox.py +6 -3
  66. streamlit/elements/widgets/slider.py +38 -42
  67. streamlit/elements/widgets/time_widgets.py +6 -12
  68. streamlit/elements/write.py +27 -6
  69. streamlit/emojis.py +1 -1
  70. streamlit/errors.py +115 -0
  71. streamlit/hello/hello.py +8 -0
  72. streamlit/hello/utils.py +2 -1
  73. streamlit/material_icon_names.py +1 -1
  74. streamlit/navigation/page.py +4 -1
  75. streamlit/proto/ArrowData_pb2.py +27 -0
  76. streamlit/proto/ArrowData_pb2.pyi +46 -0
  77. streamlit/proto/BidiComponent_pb2.py +34 -0
  78. streamlit/proto/BidiComponent_pb2.pyi +153 -0
  79. streamlit/proto/Block_pb2.py +7 -7
  80. streamlit/proto/Block_pb2.pyi +4 -1
  81. streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
  82. streamlit/proto/DeckGlJsonChart_pb2.pyi +9 -3
  83. streamlit/proto/Element_pb2.py +5 -3
  84. streamlit/proto/Element_pb2.pyi +14 -4
  85. streamlit/proto/HeightConfig_pb2.py +2 -2
  86. streamlit/proto/HeightConfig_pb2.pyi +6 -3
  87. streamlit/proto/NewSession_pb2.py +18 -18
  88. streamlit/proto/NewSession_pb2.pyi +25 -6
  89. streamlit/proto/PlotlyChart_pb2.py +8 -6
  90. streamlit/proto/PlotlyChart_pb2.pyi +3 -1
  91. streamlit/proto/Space_pb2.py +27 -0
  92. streamlit/proto/Space_pb2.pyi +42 -0
  93. streamlit/proto/WidgetStates_pb2.py +2 -2
  94. streamlit/proto/WidgetStates_pb2.pyi +13 -3
  95. streamlit/proto/WidthConfig_pb2.py +2 -2
  96. streamlit/proto/WidthConfig_pb2.pyi +6 -3
  97. streamlit/runtime/app_session.py +27 -1
  98. streamlit/runtime/caching/cache_data_api.py +4 -4
  99. streamlit/runtime/caching/cache_errors.py +4 -1
  100. streamlit/runtime/caching/cache_resource_api.py +3 -2
  101. streamlit/runtime/caching/cache_utils.py +2 -1
  102. streamlit/runtime/caching/cached_message_replay.py +3 -3
  103. streamlit/runtime/caching/hashing.py +3 -4
  104. streamlit/runtime/caching/legacy_cache_api.py +2 -1
  105. streamlit/runtime/connection_factory.py +1 -3
  106. streamlit/runtime/forward_msg_queue.py +4 -1
  107. streamlit/runtime/fragment.py +2 -1
  108. streamlit/runtime/memory_media_file_storage.py +1 -1
  109. streamlit/runtime/metrics_util.py +6 -2
  110. streamlit/runtime/runtime.py +14 -0
  111. streamlit/runtime/scriptrunner/exec_code.py +2 -1
  112. streamlit/runtime/scriptrunner/script_runner.py +2 -2
  113. streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
  114. streamlit/runtime/secrets.py +2 -4
  115. streamlit/runtime/session_manager.py +3 -1
  116. streamlit/runtime/state/common.py +30 -5
  117. streamlit/runtime/state/presentation.py +85 -0
  118. streamlit/runtime/state/safe_session_state.py +2 -2
  119. streamlit/runtime/state/session_state.py +220 -16
  120. streamlit/runtime/state/widgets.py +19 -3
  121. streamlit/runtime/websocket_session_manager.py +3 -1
  122. streamlit/source_util.py +2 -2
  123. streamlit/static/index.html +2 -2
  124. streamlit/static/manifest.json +243 -226
  125. streamlit/static/static/css/{index.CIiu7Ygf.css → index.BpABIXK9.css} +1 -1
  126. streamlit/static/static/css/index.DgR7E2CV.css +1 -0
  127. streamlit/static/static/js/{ErrorOutline.esm.DUpR0_Ka.js → ErrorOutline.esm.YoJdlW1p.js} +1 -1
  128. streamlit/static/static/js/{FileDownload.esm.CN4j9-1w.js → FileDownload.esm.Ddx8VEYy.js} +1 -1
  129. streamlit/static/static/js/{FileHelper.CaIUKG91.js → FileHelper.90EtOmj9.js} +1 -1
  130. streamlit/static/static/js/{FormClearHelper.DTcdrasw.js → FormClearHelper.BB1Km6eP.js} +1 -1
  131. streamlit/static/static/js/InputInstructions.jhH15PqV.js +1 -0
  132. streamlit/static/static/js/{Particles.CElH0XX2.js → Particles.DUsputn1.js} +1 -1
  133. streamlit/static/static/js/{ProgressBar.DetlP5aY.js → ProgressBar.DLY8H6nE.js} +1 -1
  134. streamlit/static/static/js/{Toolbar.C77ar7rq.js → Toolbar.D8nHCkuz.js} +1 -1
  135. streamlit/static/static/js/{base-input.BQft14La.js → base-input.CJGiNqed.js} +3 -3
  136. streamlit/static/static/js/{checkbox.yZOfXCeX.js → checkbox.Cpdd482O.js} +1 -1
  137. streamlit/static/static/js/{createSuper.Dh9w1cs8.js → createSuper.CuQIogbW.js} +1 -1
  138. streamlit/static/static/js/{data-grid-overlay-editor.DcuHuCyW.js → data-grid-overlay-editor.2Ufgxc6y.js} +1 -1
  139. streamlit/static/static/js/{downloader.MeHtkq8r.js → downloader.CN0K7xlu.js} +1 -1
  140. streamlit/static/static/js/{es6.VpBPGCnM.js → es6.BJcsVXQ0.js} +2 -2
  141. streamlit/static/static/js/{iframeResizer.contentWindow.yMw_ARIL.js → iframeResizer.contentWindow.XzUvQqcZ.js} +1 -1
  142. streamlit/static/static/js/index.B1ZQh4P1.js +1 -0
  143. streamlit/static/static/js/index.BKstZk0M.js +27 -0
  144. streamlit/static/static/js/{index.Cnpi3o3E.js → index.BMcFsUee.js} +1 -1
  145. streamlit/static/static/js/{index.DKv_lNO7.js → index.BR-IdcTb.js} +1 -1
  146. streamlit/static/static/js/{index.FFOzOWzC.js → index.B_dWA3vd.js} +1 -1
  147. streamlit/static/static/js/{index.Bj9JgOEC.js → index.BgnZEMVh.js} +1 -1
  148. streamlit/static/static/js/{index.Bxz2yX3P.js → index.BohqXifI.js} +1 -1
  149. streamlit/static/static/js/{index.Dbe-Q3C-.js → index.Br5nxKNj.js} +1 -1
  150. streamlit/static/static/js/{index.BjCwMzj4.js → index.BrIKVbNc.js} +2 -2
  151. streamlit/static/static/js/index.BtWUPzle.js +1 -0
  152. streamlit/static/static/js/{index.CGYqqs6j.js → index.C0RLraek.js} +1 -1
  153. streamlit/static/static/js/{index.D2QEXQq_.js → index.CAIjskgG.js} +1 -1
  154. streamlit/static/static/js/{index.6xX1278W.js → index.CAj-7vWz.js} +131 -157
  155. streamlit/static/static/js/{index.DK7hD7_w.js → index.CMtEit2O.js} +1 -1
  156. streamlit/static/static/js/{index.DNLrMXgm.js → index.CkRlykEE.js} +1 -1
  157. streamlit/static/static/js/{index.ClELlchS.js → index.CmN3FXfI.js} +1 -1
  158. streamlit/static/static/js/{index.GRUzrudl.js → index.CwbFI1_-.js} +1 -1
  159. streamlit/static/static/js/{index.Ctn27_AE.js → index.CxIUUfab.js} +27 -27
  160. streamlit/static/static/js/index.D2KPNy7e.js +1 -0
  161. streamlit/static/static/js/{index.B0H9IXUJ.js → index.D3GPA5k4.js} +3 -3
  162. streamlit/static/static/js/{index.BycLveZ4.js → index.DGAh7DMq.js} +1 -1
  163. streamlit/static/static/js/index.DKb_NvmG.js +197 -0
  164. streamlit/static/static/js/{index.BPQo7BKk.js → index.DMqgUYKq.js} +1 -1
  165. streamlit/static/static/js/{index.CH1tqnSs.js → index.DOFlg3dS.js} +1 -1
  166. streamlit/static/static/js/{index.64ejlaaT.js → index.DPUXkcQL.js} +1 -1
  167. streamlit/static/static/js/{index.B-hiXRzw.js → index.DX1xY89g.js} +1 -1
  168. streamlit/static/static/js/index.DYATBCsq.js +2 -0
  169. streamlit/static/static/js/{index.DHh-U0dK.js → index.DaSmGJ76.js} +3 -3
  170. streamlit/static/static/js/{index.DuxqVQpd.js → index.Dd7bMeLP.js} +1 -1
  171. streamlit/static/static/js/{index.B4cAbHP6.js → index.DjmmgI5U.js} +1 -1
  172. streamlit/static/static/js/{index.DcPNYEUo.js → index.Dq56CyM2.js} +1 -1
  173. streamlit/static/static/js/{index.CiAQIz1H.js → index.DuiXaS5_.js} +1 -1
  174. streamlit/static/static/js/index.DvFidMLe.js +2 -0
  175. streamlit/static/static/js/{index.C9BdUqTi.js → index.DwkhC5Pc.js} +1 -1
  176. streamlit/static/static/js/{index.B4dUQfni.js → index.Q-3sFn1v.js} +1 -1
  177. streamlit/static/static/js/{index.CMItVsFA.js → index.QJ5QO9sJ.js} +1 -1
  178. streamlit/static/static/js/{index.CTBk8Vk2.js → index.VwTaeety.js} +1 -1
  179. streamlit/static/static/js/{index.Ck8rQ9OL.js → index.YOqQbeX8.js} +1 -1
  180. streamlit/static/static/js/{input.s6pjQ49A.js → input.D4MN_FzN.js} +1 -1
  181. streamlit/static/static/js/{memory.Cuvsdfrl.js → memory.DrZjtdGT.js} +1 -1
  182. streamlit/static/static/js/{number-overlay-editor.DdgVR5m3.js → number-overlay-editor.DRwAw1In.js} +1 -1
  183. streamlit/static/static/js/{possibleConstructorReturn.CqidKeei.js → possibleConstructorReturn.exeeJQEP.js} +1 -1
  184. streamlit/static/static/js/record.B-tDciZb.js +1 -0
  185. streamlit/static/static/js/{sandbox.CCQREcJx.js → sandbox.ClO3IuUr.js} +1 -1
  186. streamlit/static/static/js/{timepicker.mkJF97Bb.js → timepicker.DAhu-vcF.js} +1 -1
  187. streamlit/static/static/js/{toConsumableArray.De7I7KVR.js → toConsumableArray.DNbljYEC.js} +1 -1
  188. streamlit/static/static/js/{uniqueId.RI1LJdtz.js → uniqueId.oG4Gvj1v.js} +1 -1
  189. streamlit/static/static/js/{useBasicWidgetState.CedkNjUW.js → useBasicWidgetState.D6sOH6oI.js} +1 -1
  190. streamlit/static/static/js/{useTextInputAutoExpand.Ca7w8dVs.js → useTextInputAutoExpand.4u3_GcuN.js} +1 -1
  191. streamlit/static/static/js/{useUpdateUiValue.DeXelfRH.js → useUpdateUiValue.F2R3eTeR.js} +1 -1
  192. streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
  193. streamlit/static/static/js/{withFullScreenWrapper.C3561XxJ.js → withFullScreenWrapper.zothJIsI.js} +1 -1
  194. streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
  195. streamlit/string_util.py +1 -3
  196. streamlit/testing/v1/app_test.py +2 -2
  197. streamlit/testing/v1/element_tree.py +23 -9
  198. streamlit/testing/v1/util.py +2 -2
  199. streamlit/type_util.py +3 -4
  200. streamlit/url_util.py +1 -3
  201. streamlit/user_info.py +1 -2
  202. streamlit/util.py +3 -1
  203. streamlit/watcher/event_based_path_watcher.py +23 -12
  204. streamlit/watcher/local_sources_watcher.py +11 -1
  205. streamlit/watcher/path_watcher.py +9 -6
  206. streamlit/watcher/polling_path_watcher.py +4 -1
  207. streamlit/watcher/util.py +2 -2
  208. streamlit/web/cli.py +51 -22
  209. streamlit/web/server/bidi_component_request_handler.py +193 -0
  210. streamlit/web/server/component_file_utils.py +97 -0
  211. streamlit/web/server/component_request_handler.py +8 -21
  212. streamlit/web/server/oidc_mixin.py +3 -1
  213. streamlit/web/server/routes.py +2 -2
  214. streamlit/web/server/server.py +9 -0
  215. streamlit/web/server/server_util.py +3 -1
  216. streamlit/web/server/upload_file_request_handler.py +3 -1
  217. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/METADATA +4 -5
  218. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/RECORD +222 -194
  219. streamlit/static/static/css/index.CHEnSPGk.css +0 -1
  220. streamlit/static/static/js/Hooks.BRba_Own.js +0 -1
  221. streamlit/static/static/js/InputInstructions.xnSDuYeQ.js +0 -1
  222. streamlit/static/static/js/index.Baqa90pe.js +0 -2
  223. streamlit/static/static/js/index.Bm3VbPB5.js +0 -1
  224. streamlit/static/static/js/index.CFMf5_ez.js +0 -197
  225. streamlit/static/static/js/index.Cj7DSzVR.js +0 -73
  226. streamlit/static/static/js/index.DH71Ezyj.js +0 -1
  227. streamlit/static/static/js/index.DW0Grddz.js +0 -1
  228. streamlit/static/static/media/MaterialSymbols-Rounded.DeCZgS-4.woff2 +0 -0
  229. {streamlit-1.50.0.data → streamlit-1.51.0.data}/scripts/streamlit.cmd +0 -0
  230. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/WHEEL +0 -0
  231. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/entry_points.txt +0 -0
  232. {streamlit-1.50.0.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
@@ -53,7 +51,7 @@ if TYPE_CHECKING:
53
51
  from streamlit.delta_generator import DeltaGenerator
54
52
  from streamlit.elements.lib.layout_utils import WidthWithoutContent
55
53
 
56
- SomeUploadedAudioFile: TypeAlias = Union[UploadedFile, DeletedFile, None]
54
+ SomeUploadedAudioFile: TypeAlias = UploadedFile | DeletedFile | None
57
55
 
58
56
  # Allowed sample rates for audio recording
59
57
  ALLOWED_SAMPLE_RATES = {8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000}
@@ -282,11 +280,13 @@ class AudioInputMixin:
282
280
  element_id = compute_and_register_element_id(
283
281
  "audio_input",
284
282
  user_key=key,
285
- key_as_main_identity=False,
283
+ # Treat the provided key as the main identity.
284
+ key_as_main_identity=True,
286
285
  dg=self.dg,
287
286
  label=label,
288
287
  help=help,
289
288
  width=width,
289
+ sample_rate=sample_rate,
290
290
  )
291
291
 
292
292
  audio_input_proto = AudioInputProto()
@@ -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
@@ -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,7 +1070,10 @@ class ButtonGroupMixin:
1047
1070
  # "feedback" in errors
1048
1071
  "feedback" if style == "borderless" else style,
1049
1072
  user_key=key,
1050
- key_as_main_identity=False,
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"},
1051
1077
  dg=self.dg,
1052
1078
  options=formatted_options,
1053
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
@@ -624,7 +624,13 @@ class ChatMixin:
624
624
  element_id = compute_and_register_element_id(
625
625
  "chat_input",
626
626
  user_key=key,
627
- key_as_main_identity=False,
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"},
628
634
  dg=self.dg,
629
635
  placeholder=placeholder,
630
636
  max_chars=max_chars,
@@ -219,7 +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=False,
222
+ key_as_main_identity=True,
223
223
  dg=self.dg,
224
224
  label=label,
225
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
@@ -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
 
@@ -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(
@@ -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 with the selected options
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
  --------
@@ -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, TypeVar, Union, cast, overload
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 = Union[int, float]
63
+ Number: TypeAlias = int | float
66
64
  IntOrNone = TypeVar("IntOrNone", int, None)
67
65
  FloatOrNone = TypeVar("FloatOrNone", float, None)
68
66
 
@@ -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, Callable, Generic, TypeVar, cast, overload
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,7 +371,12 @@ class RadioMixin:
369
371
  element_id = compute_and_register_element_id(
370
372
  "radio",
371
373
  user_key=key,
372
- key_as_main_identity=False,
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"},
373
380
  dg=self.dg,
374
381
  label=label,
375
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,7 +377,10 @@ class SelectSliderMixin:
377
377
  element_id = compute_and_register_element_id(
378
378
  "select_slider",
379
379
  user_key=key,
380
- key_as_main_identity=False,
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"},
381
384
  dg=self.dg,
382
385
  label=label,
383
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**
@@ -544,7 +545,9 @@ class SelectboxMixin:
544
545
  # Treat the provided key as the main identity. Only include
545
546
  # the options and accept_new_options in the identity computation
546
547
  # as those can invalidate the current selection.
547
- key_as_main_identity={"options", "accept_new_options", "format_func"},
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"},
548
551
  dg=self.dg,
549
552
  label=label,
550
553
  options=formatted_options,