streamlit 1.44.1__py3-none-any.whl → 1.45.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 (182) hide show
  1. streamlit/__init__.py +5 -2
  2. streamlit/commands/execution_control.py +4 -0
  3. streamlit/commands/navigation.py +2 -1
  4. streamlit/components/types/base_custom_component.py +9 -0
  5. streamlit/components/v1/custom_component.py +21 -0
  6. streamlit/config.py +45 -47
  7. streamlit/config_util.py +1 -1
  8. streamlit/delta_generator.py +5 -1
  9. streamlit/deprecation_util.py +3 -3
  10. streamlit/elements/alert.py +83 -0
  11. streamlit/elements/exception.py +35 -6
  12. streamlit/elements/html.py +58 -6
  13. streamlit/elements/iframe.py +65 -0
  14. streamlit/elements/lib/built_in_chart_utils.py +47 -36
  15. streamlit/elements/lib/dicttools.py +2 -4
  16. streamlit/elements/lib/event_utils.py +7 -5
  17. streamlit/elements/lib/file_uploader_utils.py +3 -2
  18. streamlit/elements/lib/layout_utils.py +51 -0
  19. streamlit/elements/lib/options_selector_utils.py +26 -5
  20. streamlit/elements/lib/policies.py +1 -1
  21. streamlit/elements/markdown.py +1 -2
  22. streamlit/elements/toast.py +1 -1
  23. streamlit/elements/vega_charts.py +1 -1
  24. streamlit/elements/widgets/audio_input.py +0 -42
  25. streamlit/elements/widgets/button_group.py +42 -11
  26. streamlit/elements/widgets/chat.py +1 -1
  27. streamlit/elements/widgets/multiselect.py +211 -31
  28. streamlit/elements/widgets/number_input.py +31 -5
  29. streamlit/elements/widgets/selectbox.py +225 -42
  30. streamlit/elements/widgets/text_widgets.py +29 -4
  31. streamlit/elements/widgets/time_widgets.py +3 -2
  32. streamlit/elements/write.py +14 -4
  33. streamlit/env_util.py +4 -4
  34. streamlit/errors.py +15 -0
  35. streamlit/logger.py +1 -1
  36. streamlit/material_icon_names.py +1 -1
  37. streamlit/net_util.py +2 -2
  38. streamlit/proto/Alert_pb2.py +6 -5
  39. streamlit/proto/Alert_pb2.pyi +9 -1
  40. streamlit/proto/ClientState_pb2.py +4 -4
  41. streamlit/proto/ClientState_pb2.pyi +23 -3
  42. streamlit/proto/Components_pb2.py +10 -10
  43. streamlit/proto/Components_pb2.pyi +6 -1
  44. streamlit/proto/Exception_pb2.py +4 -3
  45. streamlit/proto/Exception_pb2.pyi +9 -1
  46. streamlit/proto/ForwardMsg_pb2.pyi +4 -7
  47. streamlit/proto/IFrame_pb2.py +3 -3
  48. streamlit/proto/IFrame_pb2.pyi +8 -2
  49. streamlit/proto/MetricsEvent_pb2.py +4 -4
  50. streamlit/proto/MetricsEvent_pb2.pyi +23 -11
  51. streamlit/proto/MultiSelect_pb2.py +4 -2
  52. streamlit/proto/MultiSelect_pb2.pyi +14 -2
  53. streamlit/proto/NewSession_pb2.py +4 -4
  54. streamlit/proto/NewSession_pb2.pyi +20 -2
  55. streamlit/proto/NumberInput_pb2.py +4 -4
  56. streamlit/proto/NumberInput_pb2.pyi +4 -1
  57. streamlit/proto/Selectbox_pb2.py +4 -2
  58. streamlit/proto/Selectbox_pb2.pyi +15 -2
  59. streamlit/proto/TextInput_pb2.py +4 -4
  60. streamlit/proto/TextInput_pb2.pyi +4 -1
  61. streamlit/proto/WidthConfig_pb2.py +27 -0
  62. streamlit/proto/WidthConfig_pb2.pyi +34 -0
  63. streamlit/runtime/app_session.py +20 -12
  64. streamlit/runtime/caching/cache_errors.py +1 -1
  65. streamlit/runtime/context.py +100 -0
  66. streamlit/runtime/context_util.py +49 -0
  67. streamlit/runtime/forward_msg_cache.py +35 -230
  68. streamlit/runtime/forward_msg_queue.py +41 -23
  69. streamlit/runtime/metrics_util.py +40 -6
  70. streamlit/runtime/runtime.py +2 -60
  71. streamlit/runtime/runtime_util.py +17 -16
  72. streamlit/runtime/scriptrunner/script_runner.py +9 -1
  73. streamlit/runtime/scriptrunner_utils/script_requests.py +3 -0
  74. streamlit/runtime/scriptrunner_utils/script_run_context.py +25 -3
  75. streamlit/runtime/session_manager.py +5 -6
  76. streamlit/runtime/state/session_state_proxy.py +2 -2
  77. streamlit/static/index.html +2 -2
  78. streamlit/static/static/css/{index.BOl9eq08.css → index.DqDwtg6_.css} +1 -1
  79. streamlit/static/static/js/ErrorOutline.esm.DyIfDYvY.js +1 -0
  80. streamlit/static/static/js/{FileDownload.esm.urHTnoG1.js → FileDownload.esm.kF1FCxeJ.js} +1 -1
  81. streamlit/static/static/js/{FileHelper.C9xUPdMQ.js → FileHelper.DKt6tIeO.js} +1 -1
  82. streamlit/static/static/js/{FormClearHelper.B56TOIUD.js → FormClearHelper.DpJR9YCu.js} +1 -1
  83. streamlit/static/static/js/{Hooks.CmfGcI8T.js → Hooks.BT6PF2Zi.js} +1 -1
  84. streamlit/static/static/js/{InputInstructions.55wIEZQg.js → InputInstructions.BmnD4oa3.js} +1 -1
  85. streamlit/static/static/js/{ProgressBar.CCmWmhAk.js → ProgressBar.Ch7VNdkM.js} +2 -2
  86. streamlit/static/static/js/{RenderInPortalIfExists.RD5lXr52.js → RenderInPortalIfExists.43tDswzK.js} +1 -1
  87. streamlit/static/static/js/Toolbar.HTGsjfCP.js +1 -0
  88. streamlit/static/static/js/{base-input.CPpHElOA.js → base-input.BjeC3XFX.js} +4 -4
  89. streamlit/static/static/js/{checkbox.CFqAmEFb.js → checkbox.DIVN0GOS.js} +2 -2
  90. streamlit/static/static/js/{createSuper.CsgKz_Fb.js → createSuper.CKyBiJe0.js} +1 -1
  91. streamlit/static/static/js/{data-grid-overlay-editor.Ca14Ol57.js → data-grid-overlay-editor.CXpaXRk5.js} +1 -1
  92. streamlit/static/static/js/{downloader.zKHUWJjs.js → downloader.B-uWAyLB.js} +1 -1
  93. streamlit/static/static/js/{es6.BxIE0hzV.js → es6._eGNfJ2i.js} +2 -2
  94. streamlit/static/static/js/{iframeResizer.contentWindow.DDXicIFm.js → iframeResizer.contentWindow.CebQfV1Q.js} +1 -1
  95. streamlit/static/static/js/index.B5TWFN5r.js +1 -0
  96. streamlit/static/static/js/{index.DHfKVVrC.js → index.BAdBHmJD.js} +1 -1
  97. streamlit/static/static/js/{index.CmrEO5y1.js → index.BI9-p_-s.js} +3 -3
  98. streamlit/static/static/js/index.BYHnDZYn.js +1 -0
  99. streamlit/static/static/js/index.B_M97aPz.js +1 -0
  100. streamlit/static/static/js/{index.KqOtBFCd.js → index.BaYSBSaz.js} +1 -1
  101. streamlit/static/static/js/{index.CdkbqTPi.js → index.BaozEIL-.js} +14 -14
  102. streamlit/static/static/js/{index.Cs9td93t.js → index.BdN5swP0.js} +1 -1
  103. streamlit/static/static/js/index.BfCAp_Sj.js +1 -0
  104. streamlit/static/static/js/{index.B-cSXLfy.js → index.BqDl3eRM.js} +143 -143
  105. streamlit/static/static/js/index.C0VtYb3T.js +2 -0
  106. streamlit/static/static/js/{index.LZYrKXpZ.js → index.C1qW_Owy.js} +1 -1
  107. streamlit/static/static/js/index.C4AcBARa.js +1 -0
  108. streamlit/static/static/js/index.CCOiJRk1.js +1 -0
  109. streamlit/static/static/js/index.COvpza5W.js +1 -0
  110. streamlit/static/static/js/{index.CDo4zkBx.js → index.C_9qGjbK.js} +2 -2
  111. streamlit/static/static/js/{index.VDXwgnpn.js → index.C_nMqHLH.js} +2 -2
  112. streamlit/static/static/js/{index.DOrPk35C.js → index.ClX0ambk.js} +1 -1
  113. streamlit/static/static/js/{index.Dhuj2eHv.js → index.Coc8OVG7.js} +1 -1
  114. streamlit/static/static/js/index.CpV1hnf8.js +3 -0
  115. streamlit/static/static/js/{index.DsopOKvk.js → index.CqISBfsc.js} +54 -54
  116. streamlit/static/static/js/index.CtTgot1Z.js +3 -0
  117. streamlit/static/static/js/{index.D_Qa2jw1.js → index.CuUJHsRK.js} +1 -1
  118. streamlit/static/static/js/{index.DKn_lTbw.js → index.CxxktCLw.js} +1 -1
  119. streamlit/static/static/js/index.D1WOs2Ce.js +1 -0
  120. streamlit/static/static/js/index.DQljs-9e.js +1 -0
  121. streamlit/static/static/js/index.DZqX4P_2.js +1 -0
  122. streamlit/static/static/js/index.DajIfBOb.js +1 -0
  123. streamlit/static/static/js/{index.Bi19R12v.js → index.DuOXre0H.js} +1 -1
  124. streamlit/static/static/js/index.EWD98YhP.js +1 -0
  125. streamlit/static/static/js/{index.DXwmtOFz.js → index.EbMzSayc.js} +1 -1
  126. streamlit/static/static/js/{index.CdNWl5UD.js → index.HsXxdgGd.js} +1 -1
  127. streamlit/static/static/js/index.LaZloCTl.js +73 -0
  128. streamlit/static/static/js/{index.Cc4G8Rqb.js → index.S_1klBoy.js} +1 -1
  129. streamlit/static/static/js/index.b0Gf958T.js +12 -0
  130. streamlit/static/static/js/{index.DsxUfkY2.js → index.l6QfBDTC.js} +1 -1
  131. streamlit/static/static/js/{index.D8rTof6f.js → index.schmj9D9.js} +1051 -223
  132. streamlit/static/static/js/{index.D8rVyQy1.js → index.t--hEgTQ.js} +2 -2
  133. streamlit/static/static/js/{input.DG8cw326.js → input.VQEe_bZy.js} +2 -2
  134. streamlit/static/static/js/{memory.8AYDhEw0.js → memory.DGVHab07.js} +1 -1
  135. streamlit/static/static/js/{mergeWith.DA0rAJcB.js → mergeWith.-RIuUGoA.js} +1 -1
  136. streamlit/static/static/js/{number-overlay-editor.CfuWV-Nu.js → number-overlay-editor.wzFLIbEE.js} +1 -1
  137. streamlit/static/static/js/{possibleConstructorReturn.cdV2PGO5.js → possibleConstructorReturn.GIObu6rf.js} +1 -1
  138. streamlit/static/static/js/{sandbox.D3iuhIxb.js → sandbox.DpjSeqe2.js} +1 -1
  139. streamlit/static/static/js/{textarea.aafhCY26.js → textarea.Dz0J9LZe.js} +2 -2
  140. streamlit/static/static/js/{timepicker.B4X4SBBg.js → timepicker.BLgJZnzX.js} +4 -4
  141. streamlit/static/static/js/{toConsumableArray.BXMHXdEK.js → toConsumableArray.0OZlxz7U.js} +1 -1
  142. streamlit/static/static/js/{uniqueId.Dd1Zs3iN.js → uniqueId.DbzplC8D.js} +1 -1
  143. streamlit/static/static/js/{useBasicWidgetState.fZnKVVgz.js → useBasicWidgetState.COJZng1S.js} +1 -1
  144. streamlit/static/static/js/useOnInputChange.CgOwAHyw.js +1 -0
  145. streamlit/static/static/js/withFullScreenWrapper.CzWvNbvi.js +1 -0
  146. streamlit/static/static/media/MaterialSymbols-Rounded.DsbC8sYI.woff2 +0 -0
  147. streamlit/testing/v1/element_tree.py +8 -3
  148. streamlit/type_util.py +2 -3
  149. streamlit/user_info.py +72 -33
  150. streamlit/watcher/local_sources_watcher.py +1 -1
  151. streamlit/watcher/util.py +6 -6
  152. streamlit/web/cli.py +6 -3
  153. streamlit/web/server/routes.py +1 -59
  154. streamlit/web/server/server.py +7 -8
  155. streamlit/web/server/server_util.py +7 -6
  156. {streamlit-1.44.1.dist-info → streamlit-1.45.0.dist-info}/METADATA +4 -4
  157. {streamlit-1.44.1.dist-info → streamlit-1.45.0.dist-info}/RECORD +161 -156
  158. {streamlit-1.44.1.dist-info → streamlit-1.45.0.dist-info}/WHEEL +1 -1
  159. streamlit/static/static/js/Toolbar.BDz48EIu.js +0 -1
  160. streamlit/static/static/js/index.57sI0PzI.js +0 -1
  161. streamlit/static/static/js/index.6E7GR8Jv.js +0 -1
  162. streamlit/static/static/js/index.6w1bxtr_.js +0 -3
  163. streamlit/static/static/js/index.B4xKWXb9.js +0 -1
  164. streamlit/static/static/js/index.BJbw2HY2.js +0 -3
  165. streamlit/static/static/js/index.BUT1S9DN.js +0 -1
  166. streamlit/static/static/js/index.Be1QaPWo.js +0 -2
  167. streamlit/static/static/js/index.Bl-BqJMM.js +0 -1
  168. streamlit/static/static/js/index.C5lSqAd6.js +0 -1
  169. streamlit/static/static/js/index.CC6uDm-p.js +0 -1
  170. streamlit/static/static/js/index.DtVI4O5R.js +0 -1
  171. streamlit/static/static/js/index.GZTHUQjY.js +0 -1
  172. streamlit/static/static/js/index.LxKV_y1F.js +0 -73
  173. streamlit/static/static/js/index.Y1tjChmn.js +0 -12
  174. streamlit/static/static/js/index.ZZuB32lN.js +0 -1
  175. streamlit/static/static/js/index.lOHJHD2E.js +0 -1
  176. streamlit/static/static/js/index.sbUaFfd3.js +0 -1
  177. streamlit/static/static/js/useOnInputChange.CNxfGIgD.js +0 -1
  178. streamlit/static/static/js/withFullScreenWrapper.BvDb1IYP.js +0 -1
  179. streamlit/static/static/media/MaterialSymbols-Rounded.BFCIvovZ.woff2 +0 -0
  180. {streamlit-1.44.1.data → streamlit-1.45.0.data}/scripts/streamlit.cmd +0 -0
  181. {streamlit-1.44.1.dist-info → streamlit-1.45.0.dist-info}/entry_points.txt +0 -0
  182. {streamlit-1.44.1.dist-info → streamlit-1.45.0.dist-info}/top_level.txt +0 -0
streamlit/__init__.py CHANGED
@@ -117,6 +117,7 @@ from streamlit.runtime.state import (
117
117
  )
118
118
  from streamlit.user_info import (
119
119
  UserInfoProxy as _UserInfoProxy,
120
+ DeprecatedUserInfoProxy as _DeprecatedUserInfoProxy,
120
121
  login as _login,
121
122
  logout as _logout,
122
123
  )
@@ -277,11 +278,13 @@ fragment = _fragment
277
278
  login = _login
278
279
  logout = _logout
279
280
 
281
+ # User
282
+ user = _UserInfoProxy()
283
+
280
284
  # Experimental APIs
281
- experimental_audio_input = _main.experimental_audio_input
282
285
  experimental_dialog = _experimental_dialog_decorator
283
286
  experimental_fragment = _experimental_fragment
284
- experimental_user = _UserInfoProxy()
287
+ experimental_user = _DeprecatedUserInfoProxy()
285
288
 
286
289
  _EXPERIMENTAL_QUERY_PARAMS_DEPRECATE_MSG = "Refer to our [docs page](https://docs.streamlit.io/develop/api-reference/caching-and-state/st.query_params) for more information."
287
290
 
@@ -140,6 +140,7 @@ def rerun( # type: ignore[misc]
140
140
  if ctx and ctx.script_requests:
141
141
  query_string = ctx.query_string
142
142
  page_script_hash = ctx.page_script_hash
143
+ cached_message_hashes = ctx.cached_message_hashes
143
144
 
144
145
  ctx.script_requests.request_rerun(
145
146
  RerunData(
@@ -147,6 +148,8 @@ def rerun( # type: ignore[misc]
147
148
  page_script_hash=page_script_hash,
148
149
  fragment_id_queue=_new_fragment_id_queue(ctx, scope),
149
150
  is_fragment_scoped_rerun=scope == "fragment",
151
+ cached_message_hashes=cached_message_hashes,
152
+ context_info=ctx.context_info,
150
153
  )
151
154
  )
152
155
  # Force a yield point so the runner can do the rerun
@@ -232,6 +235,7 @@ def switch_page(page: str | Path | StreamlitPage) -> NoReturn: # type: ignore[m
232
235
  RerunData(
233
236
  query_string=ctx.query_string,
234
237
  page_script_hash=page_script_hash,
238
+ cached_message_hashes=ctx.cached_message_hashes,
235
239
  )
236
240
  )
237
241
  # Force a yield point so the runner can do the rerun
@@ -31,6 +31,7 @@ from streamlit.runtime.scriptrunner_utils.script_run_context import (
31
31
  ScriptRunContext,
32
32
  get_script_run_ctx,
33
33
  )
34
+ from streamlit.string_util import is_emoji
34
35
 
35
36
  if TYPE_CHECKING:
36
37
  from streamlit.source_util import PageHash, PageInfo
@@ -349,7 +350,7 @@ def _navigation(
349
350
  p = msg.navigation.app_pages.add()
350
351
  p.page_script_hash = page._script_hash
351
352
  p.page_name = page.title
352
- p.icon = page.icon
353
+ p.icon = f"emoji:{page.icon}" if is_emoji(page.icon) else page.icon
353
354
  p.is_default = page._default
354
355
  p.section_header = section_header
355
356
  p.url_pathname = page.url_path
@@ -60,6 +60,7 @@ class BaseCustomComponent(ABC):
60
60
  default: Any = None,
61
61
  key: str | None = None,
62
62
  on_change: WidgetCallback | None = None,
63
+ tab_index: int | None = None,
63
64
  **kwargs,
64
65
  ) -> Any:
65
66
  """An alias for create_instance."""
@@ -68,6 +69,7 @@ class BaseCustomComponent(ABC):
68
69
  default=default,
69
70
  key=key,
70
71
  on_change=on_change,
72
+ tab_index=tab_index,
71
73
  **kwargs,
72
74
  )
73
75
 
@@ -113,6 +115,7 @@ class BaseCustomComponent(ABC):
113
115
  default: Any = None,
114
116
  key: str | None = None,
115
117
  on_change: WidgetCallback | None = None,
118
+ tab_index: int | None = None,
116
119
  **kwargs,
117
120
  ) -> Any:
118
121
  """Create a new instance of the component.
@@ -131,6 +134,12 @@ class BaseCustomComponent(ABC):
131
134
  component's "widget ID".
132
135
  on_change: WidgetCallback or None
133
136
  An optional callback invoked when the widget's value changes. No arguments are passed to it.
137
+ tab_index: int or None
138
+ Specifies the tab order of the iframe containing the component.
139
+ Possible values are:
140
+ - ``None`` (default): Browser default behavior.
141
+ - ``-1``: Removes the iframe from the natural tab order, but it can still be focused programmatically.
142
+ - ``0`` or positive integer: Includes the iframe in the natural tab order.
134
143
  **kwargs
135
144
  Keyword args to pass to the component.
136
145
 
@@ -52,6 +52,7 @@ class CustomComponent(BaseCustomComponent):
52
52
  default: Any = None,
53
53
  key: str | None = None,
54
54
  on_change: WidgetCallback | None = None,
55
+ tab_index: int | None = None,
55
56
  **kwargs,
56
57
  ) -> Any:
57
58
  """An alias for create_instance."""
@@ -60,6 +61,7 @@ class CustomComponent(BaseCustomComponent):
60
61
  default=default,
61
62
  key=key,
62
63
  on_change=on_change,
64
+ tab_index=tab_index,
63
65
  **kwargs,
64
66
  )
65
67
 
@@ -70,6 +72,7 @@ class CustomComponent(BaseCustomComponent):
70
72
  default: Any = None,
71
73
  key: str | None = None,
72
74
  on_change: WidgetCallback | None = None,
75
+ tab_index: int | None = None,
73
76
  **kwargs,
74
77
  ) -> Any:
75
78
  """Create a new instance of the component.
@@ -88,6 +91,12 @@ class CustomComponent(BaseCustomComponent):
88
91
  component's "widget ID".
89
92
  on_change: WidgetCallback or None
90
93
  An optional callback invoked when the widget's value changes. No arguments are passed to it.
94
+ tab_index : int, optional
95
+ Specifies the tab order of the iframe containing the component.
96
+ Possible values are:
97
+ - ``None`` (default): Browser default behavior.
98
+ - ``-1``: Removes the iframe from the natural tab order, but it can still be focused programmatically.
99
+ - ``0`` or positive integer: Includes the iframe in the natural tab order.
91
100
  **kwargs
92
101
  Keyword args to pass to the component.
93
102
 
@@ -100,6 +109,16 @@ class CustomComponent(BaseCustomComponent):
100
109
  if len(args) > 0:
101
110
  raise MarshallComponentException(f"Argument '{args[0]}' needs a label")
102
111
 
112
+ # Validate tab_index according to web specifications
113
+ if tab_index is not None and not (
114
+ isinstance(tab_index, int)
115
+ and not isinstance(tab_index, bool)
116
+ and tab_index >= -1
117
+ ):
118
+ raise StreamlitAPIException(
119
+ "tab_index must be None, -1, or a non-negative integer."
120
+ )
121
+
103
122
  try:
104
123
  import pyarrow # noqa: F401, ICN001
105
124
 
@@ -148,6 +167,8 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
148
167
  element.component_instance.form_id = current_form_id(dg)
149
168
  if self.url is not None:
150
169
  element.component_instance.url = self.url
170
+ if tab_index is not None:
171
+ element.component_instance.tab_index = tab_index
151
172
 
152
173
  # Normally, a widget's element_hash (which determines
153
174
  # its identity across multiple runs of an app) is computed
streamlit/config.py CHANGED
@@ -17,12 +17,13 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import copy
20
+ import logging
20
21
  import os
21
22
  import secrets
22
23
  import threading
23
24
  from collections import OrderedDict
24
25
  from enum import Enum
25
- from typing import Any, Callable, Literal
26
+ from typing import Any, Callable, Final, Literal
26
27
 
27
28
  from blinker import Signal
28
29
 
@@ -55,14 +56,16 @@ _config_options: dict[str, ConfigOption] | None = None
55
56
 
56
57
 
57
58
  # Indicates that a config option was defined by the user.
58
- _USER_DEFINED = "<user defined>"
59
+ _USER_DEFINED: Final = "<user defined>"
59
60
 
60
61
  # Indicates that a config option was defined either in an environment variable
61
62
  # or via command-line flag.
62
- _DEFINED_BY_FLAG = "command-line argument or environment variable"
63
+ _DEFINED_BY_FLAG: Final = "command-line argument or environment variable"
63
64
 
64
65
  # Indicates that a config option was defined in an environment variable
65
- _DEFINED_BY_ENV_VAR = "environment variable"
66
+ _DEFINED_BY_ENV_VAR: Final = "environment variable"
67
+
68
+ _LOGGER: Final = logging.getLogger(__name__)
66
69
 
67
70
 
68
71
  class ShowErrorDetailsConfigOptions(str, Enum):
@@ -82,8 +85,9 @@ class ShowErrorDetailsConfigOptions(str, Enum):
82
85
  return val in ["false", "False", False]
83
86
 
84
87
  # Config options can be set from several places including the command-line and
85
- # the user's script. Legacy config options (true/false) will have type string when set via
86
- # command-line and bool when set via user script (e.g. st.set_option("client.showErrorDetails", False)).
88
+ # the user's script. Legacy config options (true/false) will have type string
89
+ # when set via command-line and bool when set via user script
90
+ # (e.g. st.set_option("client.showErrorDetails", False)).
87
91
 
88
92
 
89
93
  class CustomThemeCategories(str, Enum):
@@ -162,7 +166,8 @@ def set_user_option(key: str, value: Any) -> None:
162
166
  return
163
167
 
164
168
  raise StreamlitAPIException(
165
- f"{key} cannot be set on the fly. Set as command line option, e.g. streamlit run script.py --{key}, or in config.toml instead."
169
+ f"{key} cannot be set on the fly. Set as command line option, e.g. "
170
+ "streamlit run script.py --{key}, or in config.toml instead."
166
171
  )
167
172
 
168
173
 
@@ -308,8 +313,11 @@ def _create_theme_options(
308
313
  type_: type = str,
309
314
  ) -> None:
310
315
  """
311
- Create ConfigOption(s) for a theme-related config option and store it globally in this module.
312
- The same config option can be supported for multiple categories, e.g. "theme" and "theme.sidebar".
316
+ Create ConfigOption(s) for a theme-related config option and store it globally in
317
+ this module.
318
+
319
+ The same config option can be supported for multiple categories, e.g. "theme"
320
+ and "theme.sidebar".
313
321
  """
314
322
  for cat in categories:
315
323
  section = cat if cat == "theme" else f"theme.{cat.value}"
@@ -444,32 +452,6 @@ _create_option(
444
452
  type_=int,
445
453
  )
446
454
 
447
- _create_option(
448
- "global.storeCachedForwardMessagesInMemory",
449
- description="""
450
- If True, store cached ForwardMsgs in backend memory. This is an
451
- internal flag to validate a potential removal of the in-memory
452
- forward message cache.
453
- """,
454
- visibility="hidden",
455
- default_val=True,
456
- type_=bool,
457
- )
458
-
459
- _create_option(
460
- "global.includeFragmentRunsInForwardMessageCacheCount",
461
- description="""
462
- If True, the server will include fragment runs in the count for the
463
- forward message cache. The implication is that apps with fragments may
464
- see messages being removed from the cache faster. This aligns the server
465
- count with the frontend count. This is a temporary fix while we assess the
466
- design of the cache.
467
- """,
468
- visibility="hidden",
469
- default_val=False,
470
- type_=bool,
471
- )
472
-
473
455
 
474
456
  # Config Section: Logger #
475
457
  _create_section("logger", "Settings to customize Streamlit log messages.")
@@ -729,7 +711,11 @@ def _server_headless() -> bool:
729
711
  Default: false unless (1) we are on a Linux box where DISPLAY is unset, or
730
712
  (2) we are running in the Streamlit Atom plugin.
731
713
  """
732
- if env_util.IS_LINUX_OR_BSD and not os.getenv("DISPLAY"):
714
+ if (
715
+ env_util.IS_LINUX_OR_BSD
716
+ and not os.getenv("DISPLAY")
717
+ and not os.getenv("WAYLAND_DISPLAY")
718
+ ):
733
719
  # We're running in Linux and DISPLAY is unset
734
720
  return True
735
721
 
@@ -836,7 +822,9 @@ _create_option(
836
822
  description="""
837
823
  Max size, in megabytes, for files uploaded with the file_uploader.
838
824
  """,
839
- default_val=200, # If this default is changed, please also update the docstring for `DeltaGenerator.file_uploader`.
825
+ # If this default is changed, please also update the docstring
826
+ # for `DeltaGenerator.file_uploader`.
827
+ default_val=200,
840
828
  type_=int,
841
829
  )
842
830
 
@@ -853,8 +841,9 @@ _create_option(
853
841
  _create_option(
854
842
  "server.enableArrowTruncation",
855
843
  description="""
856
- Enable automatically truncating all data structures that get serialized into Arrow (e.g. DataFrames)
857
- to ensure that the size is under `server.maxMessageSize`.
844
+ Enable automatically truncating all data structures that get serialized
845
+ into Arrow (e.g. DataFrames) to ensure that the size is under
846
+ `server.maxMessageSize`.
858
847
  """,
859
848
  visibility="hidden",
860
849
  default_val=False,
@@ -1233,8 +1222,8 @@ _create_option(
1233
1222
  will take precedence over earlier ones.
1234
1223
  """,
1235
1224
  default_val=[
1236
- # NOTE: The order here is important! Project-level secrets should overwrite global
1237
- # secrets.
1225
+ # NOTE: The order here is important! Project-level secrets should overwrite
1226
+ # global secrets.
1238
1227
  file_util.get_streamlit_file_path("secrets.toml"),
1239
1228
  file_util.get_project_streamlit_file_path("secrets.toml"),
1240
1229
  ],
@@ -1370,9 +1359,18 @@ def _update_config_with_toml(raw_toml: str, where_defined: str) -> None:
1370
1359
  Tells the config system where this was set.
1371
1360
 
1372
1361
  """
1373
- import toml
1362
+ try:
1363
+ import toml
1374
1364
 
1375
- parsed_config_file = toml.loads(raw_toml)
1365
+ parsed_config_file = toml.loads(raw_toml)
1366
+ except Exception:
1367
+ # Catching any parsing exception to prevent this from breaking our
1368
+ # config change watcher logic.
1369
+ _LOGGER.exception(
1370
+ "Error parsing config toml. This is most likely due to a syntax error "
1371
+ "in the config.toml file. Please fix it and try again.",
1372
+ )
1373
+ return
1376
1374
 
1377
1375
  def process_section(section_path: str, section_data: dict[str, Any]) -> None:
1378
1376
  """Recursively process nested sections of the config file.
@@ -1415,8 +1413,7 @@ def _update_config_with_toml(raw_toml: str, where_defined: str) -> None:
1415
1413
  process_section(option_name, value)
1416
1414
  else:
1417
1415
  # It's a regular config option, set it
1418
- value = _maybe_read_env_variable(value)
1419
- _set_option(option_name, value, where_defined)
1416
+ _set_option(option_name, _maybe_read_env_variable(value), where_defined)
1420
1417
 
1421
1418
  for section, options in parsed_config_file.items():
1422
1419
  process_section(section, options)
@@ -1508,7 +1505,7 @@ def get_config_options(
1508
1505
  dict[str, ConfigOption]
1509
1506
  An ordered dict that maps config option names to their values.
1510
1507
  """
1511
- global _config_options
1508
+ global _config_options # noqa: PLW0603
1512
1509
 
1513
1510
  if not options_from_flags:
1514
1511
  options_from_flags = {}
@@ -1586,7 +1583,8 @@ def _check_conflicts() -> None:
1586
1583
  if not get_option("server.enableCORS") or get_option("global.developmentMode"):
1587
1584
  LOGGER.warning(
1588
1585
  """
1589
- Warning: the config option 'server.enableCORS=false' is not compatible with 'server.enableXsrfProtection=true'.
1586
+ Warning: the config option 'server.enableCORS=false' is not compatible with
1587
+ 'server.enableXsrfProtection=true'.
1590
1588
  As a result, 'server.enableCORS' is being overridden to 'true'.
1591
1589
 
1592
1590
  More information:
streamlit/config_util.py CHANGED
@@ -87,7 +87,7 @@ def show_config(
87
87
  append_section("[%s]" % section)
88
88
  out.append("")
89
89
 
90
- for key, option in section_options.items():
90
+ for _, option in section_options.items():
91
91
  key = option.key.split(".")[-1]
92
92
  description_paragraphs = _clean_paragraphs(option.description or "")
93
93
 
@@ -121,7 +121,7 @@ def _maybe_print_use_warning() -> None:
121
121
  """Print a warning if Streamlit is imported but not being run with `streamlit run`.
122
122
  The warning is printed only once, and is printed using the root logger.
123
123
  """
124
- global _use_warning_has_been_displayed
124
+ global _use_warning_has_been_displayed # noqa: PLW0603
125
125
 
126
126
  if not _use_warning_has_been_displayed:
127
127
  _use_warning_has_been_displayed = True
@@ -487,6 +487,10 @@ class DeltaGenerator(
487
487
  cursor=new_cursor,
488
488
  parent=dg,
489
489
  )
490
+
491
+ # Elements inherit their parent form ids.
492
+ # NOTE: Form ids aren't set in dg constructor.
493
+ output_dg._form_data = FormData(current_form_id(dg))
490
494
  else:
491
495
  # If the message was not enqueued, just return self since it's a
492
496
  # no-op from the point of view of the app.
@@ -139,7 +139,7 @@ def deprecate_obj_name(
139
139
 
140
140
  include_st_prefix
141
141
  If False, does not prefix each of the object names in the deprecation
142
- essage with `st.*`. Defaults to True.
142
+ message with `st.*`. Defaults to True.
143
143
  """
144
144
 
145
145
  return _create_deprecated_obj_wrapper(
@@ -188,13 +188,13 @@ def _create_deprecated_obj_wrapper(obj: TObj, show_warning: Callable[[], Any]) -
188
188
  return getattr(obj, attr)
189
189
 
190
190
  @staticmethod
191
- def _get_magic_functions(cls) -> list[str]:
191
+ def _get_magic_functions(self_cls) -> list[str]:
192
192
  # ignore the handful of magic functions we cannot override without
193
193
  # breaking the Wrapper.
194
194
  ignore = ("__class__", "__dict__", "__getattribute__", "__getattr__")
195
195
  return [
196
196
  name
197
- for name in dir(cls)
197
+ for name in dir(self_cls)
198
198
  if name not in ignore and name.startswith("__")
199
199
  ]
200
200
 
@@ -16,12 +16,15 @@ from __future__ import annotations
16
16
 
17
17
  from typing import TYPE_CHECKING, cast
18
18
 
19
+ from streamlit.elements.lib.layout_utils import validate_width
19
20
  from streamlit.proto.Alert_pb2 import Alert as AlertProto
21
+ from streamlit.proto.WidthConfig_pb2 import WidthConfig
20
22
  from streamlit.runtime.metrics_util import gather_metrics
21
23
  from streamlit.string_util import clean_text, validate_icon_or_emoji
22
24
 
23
25
  if TYPE_CHECKING:
24
26
  from streamlit.delta_generator import DeltaGenerator
27
+ from streamlit.elements.lib.layout_utils import WidthWithoutContent
25
28
  from streamlit.type_util import SupportsStr
26
29
 
27
30
 
@@ -32,6 +35,7 @@ class AlertMixin:
32
35
  body: SupportsStr,
33
36
  *, # keyword-only args:
34
37
  icon: str | None = None,
38
+ width: WidthWithoutContent = "stretch",
35
39
  ) -> DeltaGenerator:
36
40
  """Display error message.
37
41
 
@@ -62,6 +66,13 @@ class AlertMixin:
62
66
  Thumb Up icon. Find additional icons in the `Material Symbols \
63
67
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
64
68
  font library.
69
+ width : int or "stretch"
70
+ The desired width of the alert expressed in pixels. If this is
71
+ ``"stretch"`` (default), Streamlit sets the width of the alert to
72
+ match the width of the parent container. Otherwise, this must be an
73
+ integer. If the specified width is greater than the width of the
74
+ parent container, Streamlit sets the width of the alert to match
75
+ the width of the parent container.
65
76
 
66
77
  Example
67
78
  -------
@@ -75,6 +86,18 @@ class AlertMixin:
75
86
  alert_proto.icon = validate_icon_or_emoji(icon)
76
87
  alert_proto.body = clean_text(body)
77
88
  alert_proto.format = AlertProto.ERROR
89
+
90
+ validate_width(width)
91
+
92
+ width_config = WidthConfig()
93
+
94
+ if isinstance(width, int):
95
+ width_config.pixel_width = width
96
+ else:
97
+ width_config.use_stretch = True
98
+
99
+ alert_proto.width_config.CopyFrom(width_config)
100
+
78
101
  return self.dg._enqueue("alert", alert_proto)
79
102
 
80
103
  @gather_metrics("warning")
@@ -83,6 +106,7 @@ class AlertMixin:
83
106
  body: SupportsStr,
84
107
  *, # keyword-only args:
85
108
  icon: str | None = None,
109
+ width: WidthWithoutContent = "stretch",
86
110
  ) -> DeltaGenerator:
87
111
  """Display warning message.
88
112
 
@@ -113,6 +137,13 @@ class AlertMixin:
113
137
  Thumb Up icon. Find additional icons in the `Material Symbols \
114
138
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
115
139
  font library.
140
+ width : int or "stretch"
141
+ The desired width of the alert expressed in pixels. If this is
142
+ ``"stretch"`` (default), Streamlit sets the width of the alert to
143
+ match the width of the parent container. Otherwise, this must be an
144
+ integer. If the specified width is greater than the width of the
145
+ parent container, Streamlit sets the width of the alert to match
146
+ the width of the parent container.
116
147
 
117
148
  Example
118
149
  -------
@@ -125,6 +156,18 @@ class AlertMixin:
125
156
  alert_proto.body = clean_text(body)
126
157
  alert_proto.icon = validate_icon_or_emoji(icon)
127
158
  alert_proto.format = AlertProto.WARNING
159
+
160
+ validate_width(width)
161
+
162
+ width_config = WidthConfig()
163
+
164
+ if isinstance(width, int):
165
+ width_config.pixel_width = width
166
+ else:
167
+ width_config.use_stretch = True
168
+
169
+ alert_proto.width_config.CopyFrom(width_config)
170
+
128
171
  return self.dg._enqueue("alert", alert_proto)
129
172
 
130
173
  @gather_metrics("info")
@@ -133,6 +176,7 @@ class AlertMixin:
133
176
  body: SupportsStr,
134
177
  *, # keyword-only args:
135
178
  icon: str | None = None,
179
+ width: WidthWithoutContent = "stretch",
136
180
  ) -> DeltaGenerator:
137
181
  """Display an informational message.
138
182
 
@@ -163,6 +207,13 @@ class AlertMixin:
163
207
  Thumb Up icon. Find additional icons in the `Material Symbols \
164
208
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
165
209
  font library.
210
+ width : int or "stretch"
211
+ The desired width of the alert expressed in pixels. If this is
212
+ ``"stretch"`` (default), Streamlit sets the width of the alert to
213
+ match the width of the parent container. Otherwise, this must be an
214
+ integer. If the specified width is greater than the width of the
215
+ parent container, Streamlit sets the width of the alert to match
216
+ the width of the parent container.
166
217
 
167
218
  Example
168
219
  -------
@@ -176,6 +227,18 @@ class AlertMixin:
176
227
  alert_proto.body = clean_text(body)
177
228
  alert_proto.icon = validate_icon_or_emoji(icon)
178
229
  alert_proto.format = AlertProto.INFO
230
+
231
+ validate_width(width)
232
+
233
+ width_config = WidthConfig()
234
+
235
+ if isinstance(width, int):
236
+ width_config.pixel_width = width
237
+ else:
238
+ width_config.use_stretch = True
239
+
240
+ alert_proto.width_config.CopyFrom(width_config)
241
+
179
242
  return self.dg._enqueue("alert", alert_proto)
180
243
 
181
244
  @gather_metrics("success")
@@ -184,6 +247,7 @@ class AlertMixin:
184
247
  body: SupportsStr,
185
248
  *, # keyword-only args:
186
249
  icon: str | None = None,
250
+ width: WidthWithoutContent = "stretch",
187
251
  ) -> DeltaGenerator:
188
252
  """Display a success message.
189
253
 
@@ -214,6 +278,13 @@ class AlertMixin:
214
278
  Thumb Up icon. Find additional icons in the `Material Symbols \
215
279
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
216
280
  font library.
281
+ width : int or "stretch"
282
+ The desired width of the alert expressed in pixels. If this is
283
+ ``"stretch"`` (default), Streamlit sets the width of the alert to
284
+ match the width of the parent container. Otherwise, this must be an
285
+ integer. If the specified width is greater than the width of the
286
+ parent container, Streamlit sets the width of the alert to match
287
+ the width of the parent container.
217
288
 
218
289
  Example
219
290
  -------
@@ -226,6 +297,18 @@ class AlertMixin:
226
297
  alert_proto.body = clean_text(body)
227
298
  alert_proto.icon = validate_icon_or_emoji(icon)
228
299
  alert_proto.format = AlertProto.SUCCESS
300
+
301
+ validate_width(width)
302
+
303
+ width_config = WidthConfig()
304
+
305
+ if isinstance(width, int):
306
+ width_config.pixel_width = width
307
+ else:
308
+ width_config.use_stretch = True
309
+
310
+ alert_proto.width_config.CopyFrom(width_config)
311
+
229
312
  return self.dg._enqueue("alert", alert_proto)
230
313
 
231
314
  @property