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
@@ -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 = Union[
73
- list[SliderNumericT],
74
- tuple[()],
75
- tuple[SliderNumericT],
76
- tuple[SliderNumericT, SliderNumericT],
77
- ]
78
- SliderDatelikeSpanT: TypeAlias = Union[
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 = Union[int, float, timedelta]
89
- SliderScalar: TypeAlias = Union[int, float, date, time, datetime]
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 = Union[
92
- SliderValueT,
93
- Sequence[SliderValueT],
94
- ]
95
- SliderValue: TypeAlias = Union[
96
- SliderValueGeneric[int],
97
- SliderValueGeneric[float],
98
- SliderValueGeneric[date],
99
- SliderValueGeneric[time],
100
- SliderValueGeneric[datetime],
101
- ]
102
- SliderReturnGeneric: TypeAlias = Union[
103
- SliderValueT,
104
- tuple[SliderValueT],
105
- tuple[SliderValueT, SliderValueT],
106
- ]
107
- SliderReturn: TypeAlias = Union[
108
- SliderReturnGeneric[int],
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,7 +673,10 @@ class SliderMixin:
680
673
  element_id = compute_and_register_element_id(
681
674
  "slider",
682
675
  user_key=key,
683
- key_as_main_identity=False,
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"},
684
680
  dg=self.dg,
685
681
  label=label,
686
682
  min_value=min_value,
@@ -802,7 +798,7 @@ class SliderMixin:
802
798
  if data_type in (
803
799
  SliderProto.DATETIME,
804
800
  SliderProto.DATE,
805
- ) and max_value - min_value < timedelta(days=1):
801
+ ) and max_value - min_value < timedelta(days=1): # ty: ignore[unsupported-operator]
806
802
  step = timedelta(minutes=15)
807
803
  if format is None:
808
804
  format = cast("str", defaults[data_type]["format"]) # noqa: A001
@@ -23,13 +23,11 @@ from typing import (
23
23
  Any,
24
24
  Final,
25
25
  Literal,
26
- Union,
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 = Union[time, datetime, str, Literal["now"]]
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 = Union[date, datetime, str, Literal["today"], None]
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 = Union[NullableScalarDateValue, Sequence[NullableScalarDateValue]]
72
+ DateValue: TypeAlias = NullableScalarDateValue | Sequence[NullableScalarDateValue]
75
73
 
76
74
  # The return value of st.date_input.
77
- DateWidgetRangeReturn: TypeAlias = Union[
78
- tuple[()],
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
@@ -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,7 +31,6 @@ 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
  )
@@ -56,9 +56,6 @@ HELP_TYPES: Final[tuple[type[Any], ...]] = (
56
56
  )
57
57
 
58
58
 
59
- _TEXT_CURSOR: Final = " ▏"
60
-
61
-
62
59
  class StreamingOutput(list[Any]):
63
60
  pass
64
61
 
@@ -71,8 +68,10 @@ class WriteMixin:
71
68
  | Generator[Any, Any, Any]
72
69
  | Iterable[Any]
73
70
  | AsyncGenerator[Any, Any],
71
+ *,
72
+ cursor: str | None = None,
74
73
  ) -> list[Any] | str:
75
- """Stream a generator, iterable, or stream-like sequence to the app.
74
+ r"""Stream a generator, iterable, or stream-like sequence to the app.
76
75
 
77
76
  ``st.write_stream`` iterates through the given sequences and writes all
78
77
  chunks to the app. String chunks will be written using a typewriter effect.
@@ -92,6 +91,27 @@ class WriteMixin:
92
91
  manually define a generator function and include custom output
93
92
  parsing.
94
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
+
95
115
  Returns
96
116
  -------
97
117
  str or list
@@ -151,6 +171,7 @@ class WriteMixin:
151
171
  "this data type."
152
172
  )
153
173
 
174
+ cursor_str = cursor or ""
154
175
  stream_container: DeltaGenerator | None = None
155
176
  streamed_response: str = ""
156
177
  written_content: list[Any] = StreamingOutput()
@@ -229,7 +250,7 @@ class WriteMixin:
229
250
  streamed_response += chunk
230
251
  # Only add the streaming symbol on the second text chunk
231
252
  stream_container.markdown(
232
- streamed_response + ("" if first_text else _TEXT_CURSOR),
253
+ streamed_response + ("" if first_text else cursor_str),
233
254
  )
234
255
  elif callable(chunk):
235
256
  flush_stream_response()