streamlit 1.47.1__py3-none-any.whl → 1.48.1__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 (193) hide show
  1. streamlit/cli_util.py +1 -1
  2. streamlit/commands/echo.py +2 -2
  3. streamlit/commands/execution_control.py +1 -1
  4. streamlit/commands/page_config.py +16 -16
  5. streamlit/components/v1/component_arrow.py +4 -4
  6. streamlit/config.py +23 -5
  7. streamlit/connections/base_connection.py +2 -2
  8. streamlit/connections/snowflake_connection.py +2 -2
  9. streamlit/connections/sql_connection.py +4 -3
  10. streamlit/dataframe_util.py +1 -1
  11. streamlit/deprecation_util.py +20 -5
  12. streamlit/elements/arrow.py +105 -79
  13. streamlit/elements/deck_gl_json_chart.py +6 -6
  14. streamlit/elements/dialog_decorator.py +72 -17
  15. streamlit/elements/form.py +36 -7
  16. streamlit/elements/graphviz_chart.py +7 -0
  17. streamlit/elements/iframe.py +13 -22
  18. streamlit/elements/json.py +3 -3
  19. streamlit/elements/layouts.py +241 -75
  20. streamlit/elements/lib/built_in_chart_utils.py +11 -3
  21. streamlit/elements/lib/dialog.py +43 -0
  22. streamlit/elements/lib/file_uploader_utils.py +21 -2
  23. streamlit/elements/lib/layout_utils.py +88 -2
  24. streamlit/elements/lib/options_selector_utils.py +1 -1
  25. streamlit/elements/lib/utils.py +23 -3
  26. streamlit/elements/map.py +12 -11
  27. streamlit/elements/plotly_chart.py +21 -21
  28. streamlit/elements/pyplot.py +8 -4
  29. streamlit/elements/vega_charts.py +237 -143
  30. streamlit/elements/widgets/audio_input.py +2 -2
  31. streamlit/elements/widgets/button.py +147 -35
  32. streamlit/elements/widgets/button_group.py +9 -8
  33. streamlit/elements/widgets/camera_input.py +2 -2
  34. streamlit/elements/widgets/chat.py +8 -2
  35. streamlit/elements/widgets/checkbox.py +4 -4
  36. streamlit/elements/widgets/color_picker.py +2 -2
  37. streamlit/elements/widgets/data_editor.py +22 -15
  38. streamlit/elements/widgets/file_uploader.py +8 -2
  39. streamlit/elements/widgets/multiselect.py +27 -17
  40. streamlit/elements/widgets/number_input.py +2 -2
  41. streamlit/elements/widgets/radio.py +5 -4
  42. streamlit/elements/widgets/select_slider.py +8 -5
  43. streamlit/elements/widgets/selectbox.py +14 -4
  44. streamlit/elements/widgets/slider.py +59 -33
  45. streamlit/elements/widgets/text_widgets.py +4 -4
  46. streamlit/elements/widgets/time_widgets.py +4 -4
  47. streamlit/elements/write.py +9 -8
  48. streamlit/env_util.py +1 -1
  49. streamlit/errors.py +20 -4
  50. streamlit/file_util.py +1 -1
  51. streamlit/git_util.py +1 -1
  52. streamlit/logger.py +2 -2
  53. streamlit/proto/Block_pb2.py +39 -31
  54. streamlit/proto/Block_pb2.pyi +54 -3
  55. streamlit/proto/Button_pb2.py +4 -2
  56. streamlit/proto/Button_pb2.pyi +1 -0
  57. streamlit/proto/IFrame_pb2.py +8 -2
  58. streamlit/proto/IFrame_pb2.pyi +3 -0
  59. streamlit/runtime/caching/cache_data_api.py +15 -2
  60. streamlit/runtime/caching/cache_errors.py +1 -1
  61. streamlit/runtime/caching/cache_resource_api.py +24 -2
  62. streamlit/runtime/caching/cache_utils.py +6 -3
  63. streamlit/runtime/caching/hashing.py +6 -9
  64. streamlit/runtime/fragment.py +3 -2
  65. streamlit/runtime/runtime.py +19 -2
  66. streamlit/runtime/scriptrunner/script_runner.py +3 -3
  67. streamlit/runtime/state/common.py +2 -1
  68. streamlit/runtime/state/query_params.py +2 -1
  69. streamlit/runtime/state/session_state.py +1 -1
  70. streamlit/static/index.html +1 -1
  71. streamlit/static/manifest.json +231 -231
  72. streamlit/static/static/css/index.CQt5TjGB.css +1 -0
  73. streamlit/static/static/js/{ErrorOutline.esm.BEZPMjuG.js → ErrorOutline.esm.DjObtx4K.js} +1 -1
  74. streamlit/static/static/js/{FileDownload.esm.Dy1V9a2E.js → FileDownload.esm.Bz9nxNC5.js} +1 -1
  75. streamlit/static/static/js/{FileHelper.D0K06YBq.js → FileHelper.BrQvUXVD.js} +1 -1
  76. streamlit/static/static/js/{FormClearHelper.Cdw5Y7_m.js → FormClearHelper.DF4gFAOO.js} +1 -1
  77. streamlit/static/static/js/{Hooks.C_qx1sSw.js → Hooks.DEoLCfOE.js} +1 -1
  78. streamlit/static/static/js/{InputInstructions.D3IDU-eY.js → InputInstructions.D8zoMog9.js} +1 -1
  79. streamlit/static/static/js/Particles.CCFySwdL.js +1 -0
  80. streamlit/static/static/js/ProgressBar.COK9j1l0.js +2 -0
  81. streamlit/static/static/js/Toolbar.Dt4jIKlY.js +1 -0
  82. streamlit/static/static/js/{base-input.DMlw5p7n.js → base-input.BmvSaPd2.js} +4 -4
  83. streamlit/static/static/js/{checkbox.C7QR6llE.js → checkbox.Cgxgc0et.js} +2 -2
  84. streamlit/static/static/js/createDownloadLinkElement.ZaXNnPK4.js +1 -0
  85. streamlit/static/static/js/{createSuper.C5k_2vfB.js → createSuper.siQeagI2.js} +1 -1
  86. streamlit/static/static/js/data-grid-overlay-editor.Ct51iCb_.js +1 -0
  87. streamlit/static/static/js/{downloader.Nj6v3ioB.js → downloader.M6jQeNDf.js} +1 -1
  88. streamlit/static/static/js/{es6.CVz13CSz.js → es6.CMaUdEZ5.js} +2 -2
  89. streamlit/static/static/js/{iframeResizer.contentWindow.gZ8zjT0K.js → iframeResizer.contentWindow.C33BryyP.js} +1 -1
  90. streamlit/static/static/js/index.8GJD0eeD.js +1 -0
  91. streamlit/static/static/js/index.8QEYHMQD.js +1 -0
  92. streamlit/static/static/js/index.Ay41Wnu9.js +1 -0
  93. streamlit/static/static/js/index.BLiKiJ7_.js +1 -0
  94. streamlit/static/static/js/index.BT78cJmU.js +1 -0
  95. streamlit/static/static/js/index.BXDq9dj4.js +1 -0
  96. streamlit/static/static/js/index.BdGvnhlM.js +1 -0
  97. streamlit/static/static/js/index.BfasrT0d.js +1 -0
  98. streamlit/static/static/js/index.CCdtFMFG.js +1 -0
  99. streamlit/static/static/js/index.CFRGZDz1.js +1 -0
  100. streamlit/static/static/js/{index.MbqsiUV4.js → index.CFSFYiPA.js} +289 -289
  101. streamlit/static/static/js/{index.B2L574n6.js → index.CbdWnLqS.js} +3 -3
  102. streamlit/static/static/js/index.CeiIiXap.js +1 -0
  103. streamlit/static/static/js/index.CgZDfhN4.js +2 -0
  104. streamlit/static/static/js/{index.xfcNJBLM.js → index.Cqa4gqqN.js} +1 -1
  105. streamlit/static/static/js/index.CzX2xpyc.js +1 -0
  106. streamlit/static/static/js/index.D1EayrNh.js +73 -0
  107. streamlit/static/static/js/index.D1ErX5go.js +2 -0
  108. streamlit/static/static/js/{index.CTT2YqEU.js → index.D1jHqUJq.js} +1 -1
  109. streamlit/static/static/js/index.D5gweoL5.js +7 -0
  110. streamlit/static/static/js/index.DByVKZgq.js +1 -0
  111. streamlit/static/static/js/index.DEND45D1.js +3 -0
  112. streamlit/static/static/js/{index.CbQtRkVt.js → index.DKN5MVff.js} +162 -188
  113. streamlit/static/static/js/index.DfoxW1gP.js +3855 -0
  114. streamlit/static/static/js/index.Dtf1Ac0x.js +1 -0
  115. streamlit/static/static/js/index.DxrLhpeO.js +1 -0
  116. streamlit/static/static/js/{index.BSFzxMXi.js → index.J7o-_HIh.js} +1 -1
  117. streamlit/static/static/js/index.LU8juINp.js +197 -0
  118. streamlit/static/static/js/index.L_N2iylt.js +1 -0
  119. streamlit/static/static/js/{index.BscWuWHL.js → index.PZUX2kRz.js} +3 -3
  120. streamlit/static/static/js/index.ROjU6K0k.js +1 -0
  121. streamlit/static/static/js/index.WSNLkF94.js +1 -0
  122. streamlit/static/static/js/index.X5W3gJLn.js +1 -0
  123. streamlit/static/static/js/index.k9LYqfSL.js +1 -0
  124. streamlit/static/static/js/{index.D3wOJJsg.js → index.pnHtHv_c.js} +12 -12
  125. streamlit/static/static/js/index.tPUXqsfW.js +1 -0
  126. streamlit/static/static/js/index.tsvTLdio.js +12 -0
  127. streamlit/static/static/js/{input.D_45B0P-.js → input.DZd6EQlV.js} +2 -2
  128. streamlit/static/static/js/{memory.BmhrRyO2.js → memory.ptkfuI71.js} +1 -1
  129. streamlit/static/static/js/{mergeWith.DvOME7eH.js → mergeWith.GRNk8iwv.js} +1 -1
  130. streamlit/static/static/js/{number-overlay-editor.BRNxOzEZ.js → number-overlay-editor.DXS2qb1U.js} +1 -1
  131. streamlit/static/static/js/{possibleConstructorReturn.C5GiK_Ob.js → possibleConstructorReturn.Bd4ImlQ9.js} +1 -1
  132. streamlit/static/static/js/{sandbox.B-Q9S7vW.js → sandbox.DsH8LuID.js} +1 -1
  133. streamlit/static/static/js/{timepicker.DOMbfm_a.js → timepicker.QVekV78C.js} +1 -1
  134. streamlit/static/static/js/{toConsumableArray.CbNz0Ciu.js → toConsumableArray.BJvaP8gb.js} +1 -1
  135. streamlit/static/static/js/{uniqueId.-ygIU7IL.js → uniqueId.D_5M8Dgf.js} +1 -1
  136. streamlit/static/static/js/{useBasicWidgetState.Bx3VaRHk.js → useBasicWidgetState.DB3vMS9V.js} +1 -1
  137. streamlit/static/static/js/useTextInputAutoExpand.CBkGkaRt.js +2 -0
  138. streamlit/static/static/js/useUpdateUiValue.C7ZKpLQK.js +1 -0
  139. streamlit/static/static/js/withFullScreenWrapper.C-gXt0Rl.js +1 -0
  140. streamlit/temporary_directory.py +5 -3
  141. streamlit/testing/v1/app_test.py +4 -1
  142. streamlit/testing/v1/element_tree.py +4 -5
  143. streamlit/type_util.py +10 -3
  144. streamlit/user_info.py +6 -1
  145. streamlit/util.py +11 -1
  146. streamlit/watcher/local_sources_watcher.py +4 -3
  147. streamlit/web/bootstrap.py +18 -12
  148. streamlit/web/cli.py +2 -1
  149. streamlit/web/server/server.py +72 -21
  150. {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/METADATA +14 -2
  151. {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/RECORD +155 -155
  152. streamlit/static/static/css/index.CsLB_Bnz.css +0 -1
  153. streamlit/static/static/js/ProgressBar.EhJ_lCOf.js +0 -2
  154. streamlit/static/static/js/RenderInPortalIfExists.D6a0mMll.js +0 -1
  155. streamlit/static/static/js/Toolbar.D6yqQ65-.js +0 -1
  156. streamlit/static/static/js/createDownloadLinkElement.DZMwyjvU.js +0 -1
  157. streamlit/static/static/js/data-grid-overlay-editor.CoquyZNK.js +0 -1
  158. streamlit/static/static/js/index.B3n-pURl.js +0 -2
  159. streamlit/static/static/js/index.B9jJp9aE.js +0 -1
  160. streamlit/static/static/js/index.BBVtld-D.js +0 -1
  161. streamlit/static/static/js/index.BKHPnvYd.js +0 -1
  162. streamlit/static/static/js/index.B_1CXynz.js +0 -1
  163. streamlit/static/static/js/index.Bm1LklYO.js +0 -1
  164. streamlit/static/static/js/index.Byi6__iF.js +0 -1
  165. streamlit/static/static/js/index.BzJeMpQ-.js +0 -197
  166. streamlit/static/static/js/index.C4tw7-Cl.js +0 -2
  167. streamlit/static/static/js/index.CG0C49ex.js +0 -1
  168. streamlit/static/static/js/index.CMuSJPv-.js +0 -1
  169. streamlit/static/static/js/index.COPFcr_K.js +0 -3855
  170. streamlit/static/static/js/index.CU3TLDlu.js +0 -1
  171. streamlit/static/static/js/index.CVKKDwaf.js +0 -1
  172. streamlit/static/static/js/index.CWZeK3mV.js +0 -12
  173. streamlit/static/static/js/index.CWbiNJQl.js +0 -1
  174. streamlit/static/static/js/index.CWxefYP6.js +0 -73
  175. streamlit/static/static/js/index.DOdWa88b.js +0 -1
  176. streamlit/static/static/js/index.DXtnaPua.js +0 -1
  177. streamlit/static/static/js/index.DatDwFl3.js +0 -3
  178. streamlit/static/static/js/index.DeWYPvQR.js +0 -1
  179. streamlit/static/static/js/index.Do4vzIvK.js +0 -1
  180. streamlit/static/static/js/index.Dvrstlh8.js +0 -1
  181. streamlit/static/static/js/index.DvznfdF_.js +0 -1
  182. streamlit/static/static/js/index.U1vvXeGn.js +0 -1
  183. streamlit/static/static/js/index._WAuWRkp.js +0 -7
  184. streamlit/static/static/js/index.bwA9_eWC.js +0 -1
  185. streamlit/static/static/js/index.m1njXuKl.js +0 -1
  186. streamlit/static/static/js/index.mihWZKb1.js +0 -1
  187. streamlit/static/static/js/useOnInputChange.CDZx-L6q.js +0 -1
  188. streamlit/static/static/js/useTextInputAutoExpand.BuE9l5TG.js +0 -2
  189. streamlit/static/static/js/withFullScreenWrapper.DWXejOhQ.js +0 -1
  190. {streamlit-1.47.1.data → streamlit-1.48.1.data}/scripts/streamlit.cmd +0 -0
  191. {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/WHEEL +0 -0
  192. {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/entry_points.txt +0 -0
  193. {streamlit-1.47.1.dist-info → streamlit-1.48.1.dist-info}/top_level.txt +0 -0
@@ -296,6 +296,12 @@ class FileUploaderMixin:
296
296
  example, to only accept JPG/JPEG and PNG files, use
297
297
  ``["jpg", "jpeg", "png"]``.
298
298
 
299
+ .. note::
300
+ This is a best-effort check, but doesn't provide a
301
+ security guarantee against users uploading files of other types
302
+ or type extensions. The correct handling of uploaded files is
303
+ part of the app developer's responsibility.
304
+
299
305
  accept_multiple_files : bool
300
306
  Whether to accept more than one file in a submission. If this is
301
307
  ``False`` (default), the user can only submit one file at a time.
@@ -320,8 +326,8 @@ class FileUploaderMixin:
320
326
  An optional callback invoked when this file_uploader's value
321
327
  changes.
322
328
 
323
- args : tuple
324
- An optional tuple of args to pass to the callback.
329
+ args : list or tuple
330
+ An optional list or tuple of args to pass to the callback.
325
331
 
326
332
  kwargs : dict
327
333
  An optional dict of kwargs to pass to the callback.
@@ -16,7 +16,16 @@ from __future__ import annotations
16
16
 
17
17
  from collections.abc import Sequence
18
18
  from textwrap import dedent
19
- from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, cast, overload
19
+ from typing import (
20
+ TYPE_CHECKING,
21
+ Any,
22
+ Callable,
23
+ Generic,
24
+ Literal,
25
+ TypeVar,
26
+ cast,
27
+ overload,
28
+ )
20
29
 
21
30
  from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
22
31
  from streamlit.elements.lib.form_utils import current_form_id
@@ -51,7 +60,6 @@ from streamlit.runtime.metrics_util import gather_metrics
51
60
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
52
61
  from streamlit.runtime.state import register_widget
53
62
  from streamlit.type_util import (
54
- T,
55
63
  is_iterable,
56
64
  )
57
65
 
@@ -66,6 +74,8 @@ if TYPE_CHECKING:
66
74
  WidgetKwargs,
67
75
  )
68
76
 
77
+ T = TypeVar("T")
78
+
69
79
 
70
80
  class MultiSelectSerde(Generic[T]):
71
81
  options: Sequence[T]
@@ -245,7 +255,7 @@ class MultiSelectMixin:
245
255
 
246
256
  Parameters
247
257
  ----------
248
- label: str
258
+ label : str
249
259
  A short label explaining to the user what this select widget is for.
250
260
  The label can optionally contain GitHub-flavored Markdown of the
251
261
  following types: Bold, Italics, Strikethroughs, Inline Code, Links,
@@ -267,27 +277,27 @@ class MultiSelectMixin:
267
277
  .. |st.markdown| replace:: ``st.markdown``
268
278
  .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
269
279
 
270
- options: Iterable
280
+ options : Iterable
271
281
  Labels for the select options in an ``Iterable``. This can be a
272
282
  ``list``, ``set``, or anything supported by ``st.dataframe``. If
273
283
  ``options`` is dataframe-like, the first column will be used. Each
274
284
  label will be cast to ``str`` internally by default.
275
285
 
276
- default: Iterable of V, V, or None
286
+ default : Iterable of V, V, or None
277
287
  List of default values. Can also be a single value.
278
288
 
279
- format_func: function
289
+ format_func : function
280
290
  Function to modify the display of the options. It receives
281
291
  the raw option as an argument and should output the label to be
282
292
  shown for that option. This has no impact on the return value of
283
293
  the command.
284
294
 
285
- key: str or int
295
+ key : str or int
286
296
  An optional string or integer to use as the unique key for the widget.
287
297
  If this is omitted, a key will be generated for the widget
288
298
  based on its content. No two widgets may have the same key.
289
299
 
290
- help: str or None
300
+ help : str or None
291
301
  A tooltip that gets displayed next to the widget label. Streamlit
292
302
  only displays the tooltip when ``label_visibility="visible"``. If
293
303
  this is ``None`` (default), no tooltip is displayed.
@@ -296,19 +306,19 @@ class MultiSelectMixin:
296
306
  including the Markdown directives described in the ``body``
297
307
  parameter of ``st.markdown``.
298
308
 
299
- on_change: callable
309
+ on_change : callable
300
310
  An optional callback invoked when this widget's value changes.
301
311
 
302
- args: tuple
303
- An optional tuple of args to pass to the callback.
312
+ args : list or tuple
313
+ An optional list or tuple of args to pass to the callback.
304
314
 
305
- kwargs: dict
315
+ kwargs : dict
306
316
  An optional dict of kwargs to pass to the callback.
307
317
 
308
- max_selections: int
318
+ max_selections : int
309
319
  The max selections that can be selected at a time.
310
320
 
311
- placeholder: str or None
321
+ placeholder : str or None
312
322
  A string to display when no options are selected.
313
323
  If this is ``None`` (default), the widget displays placeholder text
314
324
  based on the widget's configuration:
@@ -323,17 +333,17 @@ class MultiSelectMixin:
323
333
  and ``accept_new_options=False``. The widget is also disabled in
324
334
  this case.
325
335
 
326
- disabled: bool
336
+ disabled : bool
327
337
  An optional boolean that disables the multiselect widget if set
328
338
  to ``True``. The default is ``False``.
329
339
 
330
- label_visibility: "visible", "hidden", or "collapsed"
340
+ label_visibility : "visible", "hidden", or "collapsed"
331
341
  The visibility of the label. The default is ``"visible"``. If this
332
342
  is ``"hidden"``, Streamlit displays an empty spacer instead of the
333
343
  label, which can help keep the widget aligned with other widgets.
334
344
  If this is ``"collapsed"``, Streamlit displays no label or spacer.
335
345
 
336
- accept_new_options: bool
346
+ accept_new_options : bool
337
347
  Whether the user can add selections that aren't included in ``options``.
338
348
  If this is ``False`` (default), the user can only select from the
339
349
  items in ``options``. If this is ``True``, the user can enter new
@@ -317,8 +317,8 @@ class NumberInputMixin:
317
317
  on_change : callable
318
318
  An optional callback invoked when this number_input's value changes.
319
319
 
320
- args : tuple
321
- An optional tuple of args to pass to the callback.
320
+ args : list or tuple
321
+ An optional list or tuple of args to pass to the callback.
322
322
 
323
323
  kwargs : dict
324
324
  An optional dict of kwargs to pass to the callback.
@@ -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, cast, overload
19
+ from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, cast, overload
20
20
 
21
21
  from typing_extensions import Never
22
22
 
@@ -52,7 +52,6 @@ from streamlit.runtime.state import (
52
52
  register_widget,
53
53
  )
54
54
  from streamlit.type_util import (
55
- T,
56
55
  check_python_comparable,
57
56
  )
58
57
 
@@ -61,6 +60,8 @@ if TYPE_CHECKING:
61
60
 
62
61
  from streamlit.delta_generator import DeltaGenerator
63
62
 
63
+ T = TypeVar("T")
64
+
64
65
 
65
66
  @dataclass
66
67
  class RadioSerde(Generic[T]):
@@ -228,8 +229,8 @@ class RadioMixin:
228
229
  on_change : callable
229
230
  An optional callback invoked when this radio's value changes.
230
231
 
231
- args : tuple
232
- An optional tuple of args to pass to the callback.
232
+ args : list or tuple
233
+ An optional list or tuple of args to pass to the callback.
233
234
 
234
235
  kwargs : dict
235
236
  An optional dict of kwargs to pass to the callback.
@@ -21,6 +21,7 @@ from typing import (
21
21
  Any,
22
22
  Callable,
23
23
  Generic,
24
+ TypeVar,
24
25
  cast,
25
26
  overload,
26
27
  )
@@ -57,7 +58,7 @@ from streamlit.runtime.state import (
57
58
  WidgetKwargs,
58
59
  register_widget,
59
60
  )
60
- from streamlit.type_util import T, check_python_comparable
61
+ from streamlit.type_util import check_python_comparable
61
62
 
62
63
  if TYPE_CHECKING:
63
64
  from collections.abc import Sequence
@@ -66,6 +67,8 @@ if TYPE_CHECKING:
66
67
  from streamlit.elements.lib.layout_utils import WidthWithoutContent
67
68
  from streamlit.runtime.state.common import RegisterWidgetResult
68
69
 
70
+ T = TypeVar("T")
71
+
69
72
 
70
73
  def _is_range_value(value: T | Sequence[T]) -> TypeGuard[Sequence[T]]:
71
74
  return isinstance(value, (list, tuple))
@@ -94,7 +97,7 @@ class SelectSliderSerde(Generic[T]):
94
97
  # If the original value was a list/tuple, so will be the output (and vice versa)
95
98
  return return_value if self.is_range_value else return_value[0]
96
99
 
97
- def _as_index_list(self, v: object) -> list[int]:
100
+ def _as_index_list(self, v: Any) -> list[int]:
98
101
  if _is_range_value(v):
99
102
  slider_value = [index_(self.options, val) for val in v]
100
103
  start, end = slider_value
@@ -228,8 +231,8 @@ class SelectSliderMixin:
228
231
  on_change : callable
229
232
  An optional callback invoked when this select_slider's value changes.
230
233
 
231
- args : tuple
232
- An optional tuple of args to pass to the callback.
234
+ args : list or tuple
235
+ An optional list or tuple of args to pass to the callback.
233
236
 
234
237
  kwargs : dict
235
238
  An optional dict of kwargs to pass to the callback.
@@ -352,7 +355,7 @@ class SelectSliderMixin:
352
355
  if len(opt) == 0:
353
356
  raise StreamlitAPIException("The `options` argument needs to be non-empty")
354
357
 
355
- def as_index_list(v: object) -> list[int]:
358
+ def as_index_list(v: Any) -> list[int]:
356
359
  if _is_range_value(v):
357
360
  slider_value = [index_(opt, val) for val in v]
358
361
  start, end = slider_value
@@ -14,7 +14,16 @@
14
14
  from __future__ import annotations
15
15
 
16
16
  from textwrap import dedent
17
- from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, cast, overload
17
+ from typing import (
18
+ TYPE_CHECKING,
19
+ Any,
20
+ Callable,
21
+ Generic,
22
+ Literal,
23
+ TypeVar,
24
+ cast,
25
+ overload,
26
+ )
18
27
 
19
28
  from typing_extensions import Never
20
29
 
@@ -54,7 +63,6 @@ from streamlit.runtime.state import (
54
63
  register_widget,
55
64
  )
56
65
  from streamlit.type_util import (
57
- T,
58
66
  check_python_comparable,
59
67
  )
60
68
 
@@ -63,6 +71,8 @@ if TYPE_CHECKING:
63
71
 
64
72
  from streamlit.delta_generator import DeltaGenerator
65
73
 
74
+ T = TypeVar("T")
75
+
66
76
 
67
77
  class SelectboxSerde(Generic[T]):
68
78
  options: Sequence[T]
@@ -336,8 +346,8 @@ class SelectboxMixin:
336
346
  on_change : callable
337
347
  An optional callback invoked when this selectbox's value changes.
338
348
 
339
- args : tuple
340
- An optional tuple of args to pass to the callback.
349
+ args : list or tuple
350
+ An optional list or tuple of args to pass to the callback.
341
351
 
342
352
  kwargs : dict
343
353
  An optional dict of kwargs to pass to the callback.
@@ -555,8 +555,8 @@ class SliderMixin:
555
555
  on_change : callable
556
556
  An optional callback invoked when this slider's value changes.
557
557
 
558
- args : tuple
559
- An optional tuple of args to pass to the callback.
558
+ args : list or tuple
559
+ An optional list or tuple of args to pass to the callback.
560
560
 
561
561
  kwargs : dict
562
562
  An optional dict of kwargs to pass to the callback.
@@ -723,8 +723,7 @@ class SliderMixin:
723
723
  )
724
724
 
725
725
  # Simplify future logic by always making value a list
726
- if single_value:
727
- value = [value]
726
+ prepared_value: Sequence[SliderScalar] = [value] if single_value else value # ty: ignore[invalid-assignment]
728
727
 
729
728
  def value_to_generic_type(v: Any) -> SliderProto.DataType.ValueType:
730
729
  if isinstance(v, Integral):
@@ -736,26 +735,32 @@ class SliderMixin:
736
735
  def all_same_type(items: Any) -> bool:
737
736
  return len(set(map(value_to_generic_type, items))) < 2
738
737
 
739
- if not all_same_type(value):
738
+ if not all_same_type(prepared_value):
740
739
  raise StreamlitAPIException(
741
740
  "Slider tuple/list components must be of the same type.\n"
742
- f"But were: {list(map(type, value))}"
741
+ f"But were: {list(map(type, prepared_value))}"
743
742
  )
744
743
 
745
744
  data_type = (
746
- SliderProto.INT if len(value) == 0 else value_to_generic_type(value[0])
745
+ SliderProto.INT
746
+ if len(prepared_value) == 0
747
+ else value_to_generic_type(prepared_value[0])
747
748
  )
748
749
 
749
- datetime_min = time.min
750
- datetime_max = time.max
750
+ datetime_min: datetime | time = time.min
751
+ datetime_max: datetime | time = time.max
751
752
  if data_type == SliderProto.TIME:
752
- datetime_min = time.min.replace(tzinfo=value[0].tzinfo)
753
- datetime_max = time.max.replace(tzinfo=value[0].tzinfo)
753
+ prepared_value = cast("Sequence[time]", prepared_value)
754
+
755
+ datetime_min = time.min.replace(tzinfo=prepared_value[0].tzinfo)
756
+ datetime_max = time.max.replace(tzinfo=prepared_value[0].tzinfo)
754
757
  if data_type in (SliderProto.DATETIME, SliderProto.DATE):
755
- datetime_min = value[0] - timedelta(days=14)
756
- datetime_max = value[0] + timedelta(days=14)
758
+ prepared_value = cast("Sequence[datetime]", prepared_value)
759
+
760
+ datetime_min = prepared_value[0] - timedelta(days=14)
761
+ datetime_max = prepared_value[0] + timedelta(days=14)
757
762
 
758
- defaults: Final = {
763
+ defaults: Final[dict[SliderProto.DataType.ValueType, dict[str, Any]]] = {
759
764
  SliderProto.INT: {
760
765
  "min_value": 0,
761
766
  "max_value": 100,
@@ -846,20 +851,20 @@ class SliderMixin:
846
851
  # Ensure that min <= value(s) <= max, adjusting the bounds as necessary.
847
852
  min_value = min(min_value, max_value)
848
853
  max_value = max(min_value, max_value)
849
- if len(value) == 1:
850
- min_value = min(value[0], min_value)
851
- max_value = max(value[0], max_value)
852
- elif len(value) == 2:
853
- start, end = value
854
- if start > end:
854
+ if len(prepared_value) == 1:
855
+ min_value = min(prepared_value[0], min_value)
856
+ max_value = max(prepared_value[0], max_value)
857
+ elif len(prepared_value) == 2:
858
+ start, end = prepared_value
859
+ if start > end: # type: ignore[operator]
855
860
  # Swap start and end, since they seem reversed
856
861
  start, end = end, start
857
- value = start, end
862
+ prepared_value = start, end
858
863
  min_value = min(start, min_value)
859
864
  max_value = max(end, max_value)
860
865
  else:
861
866
  # Empty list, so let's just use the outer bounds
862
- value = [min_value, max_value]
867
+ prepared_value = [min_value, max_value]
863
868
 
864
869
  # Bounds checks. JSNumber produces human-readable exceptions that
865
870
  # we simply re-package as StreamlitAPIExceptions.
@@ -881,12 +886,20 @@ class SliderMixin:
881
886
  orig_tz = None
882
887
  # Convert dates or times into datetimes
883
888
  if data_type == SliderProto.TIME:
884
- value = list(map(_time_to_datetime, value))
889
+ prepared_value = cast("Sequence[time]", prepared_value)
890
+ min_value = cast("time", min_value)
891
+ max_value = cast("time", max_value)
892
+
893
+ prepared_value = list(map(_time_to_datetime, prepared_value))
885
894
  min_value = _time_to_datetime(min_value)
886
895
  max_value = _time_to_datetime(max_value)
887
896
 
888
897
  if data_type == SliderProto.DATE:
889
- value = list(map(_date_to_datetime, value))
898
+ prepared_value = cast("Sequence[date]", prepared_value)
899
+ min_value = cast("date", min_value)
900
+ max_value = cast("date", max_value)
901
+
902
+ prepared_value = list(map(_date_to_datetime, prepared_value))
890
903
  min_value = _date_to_datetime(min_value)
891
904
  max_value = _date_to_datetime(max_value)
892
905
 
@@ -900,17 +913,25 @@ class SliderMixin:
900
913
 
901
914
  # Now, convert to microseconds (so we can serialize datetime to a long)
902
915
  if data_type in TIMELIKE_TYPES:
916
+ prepared_value = cast("Sequence[datetime]", prepared_value)
917
+ min_value = cast("datetime", min_value)
918
+ max_value = cast("datetime", max_value)
919
+ step = cast("timedelta", step)
920
+
903
921
  # Restore times/datetimes to original timezone (dates are always naive)
904
922
  orig_tz = (
905
- value[0].tzinfo
923
+ prepared_value[0].tzinfo
906
924
  if data_type in (SliderProto.TIME, SliderProto.DATETIME)
907
925
  else None
908
926
  )
909
927
 
910
- value = list(map(_datetime_to_micros, value))
928
+ prepared_value = list(map(_datetime_to_micros, prepared_value))
911
929
  min_value = _datetime_to_micros(min_value)
912
930
  max_value = _datetime_to_micros(max_value)
913
- step = _delta_to_micros(cast("timedelta", step))
931
+ step = _delta_to_micros(step)
932
+
933
+ # At this point, prepared_value is expected to be a list of floats:
934
+ prepared_value = cast("list[float]", prepared_value)
914
935
 
915
936
  # It would be great if we could guess the number of decimal places from
916
937
  # the `step` argument, but this would only be meaningful if step were a
@@ -922,7 +943,7 @@ class SliderMixin:
922
943
  slider_proto.id = element_id
923
944
  slider_proto.label = label
924
945
  slider_proto.format = format
925
- slider_proto.default[:] = value
946
+ slider_proto.default[:] = prepared_value
926
947
  slider_proto.min = min_value
927
948
  slider_proto.max = max_value
928
949
  slider_proto.step = cast("float", step)
@@ -937,7 +958,12 @@ class SliderMixin:
937
958
  if help is not None:
938
959
  slider_proto.help = dedent(help)
939
960
 
940
- serde = SliderSerde(value, data_type, single_value, orig_tz)
961
+ serde = SliderSerde(
962
+ prepared_value,
963
+ data_type,
964
+ single_value,
965
+ orig_tz,
966
+ )
941
967
 
942
968
  widget_state = register_widget(
943
969
  slider_proto.id,
@@ -953,16 +979,16 @@ class SliderMixin:
953
979
  if widget_state.value_changed:
954
980
  # Min/Max bounds checks when the value is updated.
955
981
  serialized_values = serde.serialize(widget_state.value)
956
- for value in serialized_values:
982
+ for serialized_value in serialized_values:
957
983
  # Use the deserialized values for more readable error messages for dates/times
958
- deserialized_value = serde.deserialize_single_value(value)
984
+ deserialized_value = serde.deserialize_single_value(serialized_value)
959
985
 
960
- if value < slider_proto.min:
986
+ if serialized_value < slider_proto.min:
961
987
  raise StreamlitValueBelowMinError(
962
988
  value=deserialized_value,
963
989
  min_value=serde.deserialize_single_value(slider_proto.min),
964
990
  )
965
- if value > slider_proto.max:
991
+ if serialized_value > slider_proto.max:
966
992
  raise StreamlitValueAboveMaxError(
967
993
  value=deserialized_value,
968
994
  max_value=serde.deserialize_single_value(slider_proto.max),
@@ -206,8 +206,8 @@ class TextWidgetsMixin:
206
206
  on_change : callable
207
207
  An optional callback invoked when this text input's value changes.
208
208
 
209
- args : tuple
210
- An optional tuple of args to pass to the callback.
209
+ args : list or tuple
210
+ An optional list or tuple of args to pass to the callback.
211
211
 
212
212
  kwargs : dict
213
213
  An optional dict of kwargs to pass to the callback.
@@ -535,8 +535,8 @@ class TextWidgetsMixin:
535
535
  on_change : callable
536
536
  An optional callback invoked when this text_area's value changes.
537
537
 
538
- args : tuple
539
- An optional tuple of args to pass to the callback.
538
+ args : list or tuple
539
+ An optional list or tuple of args to pass to the callback.
540
540
 
541
541
  kwargs : dict
542
542
  An optional dict of kwargs to pass to the callback.
@@ -420,8 +420,8 @@ class TimeWidgetsMixin:
420
420
  on_change : callable
421
421
  An optional callback invoked when this time_input's value changes.
422
422
 
423
- args : tuple
424
- An optional tuple of args to pass to the callback.
423
+ args : list or tuple
424
+ An optional list or tuple of args to pass to the callback.
425
425
 
426
426
  kwargs : dict
427
427
  An optional dict of kwargs to pass to the callback.
@@ -753,8 +753,8 @@ class TimeWidgetsMixin:
753
753
  on_change : callable
754
754
  An optional callback invoked when this date_input's value changes.
755
755
 
756
- args : tuple
757
- An optional tuple of args to pass to the callback.
756
+ args : list or tuple
757
+ An optional list or tuple of args to pass to the callback.
758
758
 
759
759
  kwargs : dict
760
760
  An optional dict of kwargs to pass to the callback.
@@ -86,7 +86,8 @@ class WriteMixin:
86
86
  The generator or iterable to stream.
87
87
 
88
88
  If you pass an async generator, Streamlit will internally convert
89
- it to a sync generator.
89
+ it to a sync generator. If the generator depends on a cached object
90
+ with async references, this can raise an error.
90
91
 
91
92
  .. note::
92
93
  To use additional LLM libraries, you can create a wrapper to
@@ -208,7 +209,7 @@ class WriteMixin:
208
209
  if type_util.is_type(chunk, "langchain_core.messages.ai.AIMessageChunk"):
209
210
  # Try to convert LangChain message chunk to a string:
210
211
  try:
211
- chunk = chunk.content or "" # noqa: PLW2901
212
+ chunk = chunk.content or "" # noqa: PLW2901 # type: ignore[possibly-unbound-attribute]
212
213
  except AttributeError as err:
213
214
  raise StreamlitAPIException(
214
215
  "Failed to parse the LangChain AIMessageChunk. "
@@ -380,19 +381,19 @@ class WriteMixin:
380
381
 
381
382
  Oh, one more thing: ``st.write`` accepts chart objects too! For example:
382
383
 
383
- >>> import streamlit as st
384
- >>> import pandas as pd
385
- >>> import numpy as np
386
384
  >>> import altair as alt
385
+ >>> import pandas as pd
386
+ >>> import streamlit as st
387
+ >>> from numpy.random import default_rng as rng
387
388
  >>>
388
- >>> df = pd.DataFrame(np.random.randn(200, 3), columns=["a", "b", "c"])
389
- >>> c = (
389
+ >>> df = pd.DataFrame(rng(0).standard_normal((200, 3)), columns=["a", "b", "c"])
390
+ >>> chart = (
390
391
  ... alt.Chart(df)
391
392
  ... .mark_circle()
392
393
  ... .encode(x="a", y="b", size="c", color="c", tooltip=["a", "b", "c"])
393
394
  ... )
394
395
  >>>
395
- >>> st.write(c)
396
+ >>> st.write(chart)
396
397
 
397
398
  .. output::
398
399
  https://doc-vega-lite-chart.streamlit.app/
streamlit/env_util.py CHANGED
@@ -19,7 +19,7 @@ import platform
19
19
  import re
20
20
  import sys
21
21
 
22
- SYSTEM = platform.system().lower()
22
+ SYSTEM = platform.system().lower() # ty: ignore[unresolved-attribute]
23
23
  IS_WINDOWS = SYSTEM == "windows"
24
24
  IS_DARWIN = SYSTEM == "darwin"
25
25
  IS_LINUX_OR_BSD = (SYSTEM == "linux") or ("bsd" in SYSTEM)
streamlit/errors.py CHANGED
@@ -239,22 +239,38 @@ class StreamlitInvalidColumnSpecError(LocalizableStreamlitException):
239
239
  class StreamlitInvalidVerticalAlignmentError(LocalizableStreamlitException):
240
240
  """Exception raised when an invalid value is specified for vertical_alignment."""
241
241
 
242
- def __init__(self, vertical_alignment: str) -> None:
242
+ def __init__(self, vertical_alignment: str, element_type: str) -> None:
243
243
  super().__init__(
244
- 'The `vertical_alignment` argument to `st.columns` must be `"top"`, `"center"`, or `"bottom"`. \n'
244
+ "The `vertical_alignment` argument to `{element_type}` must be "
245
+ '`"top"`, `"center"`, `"bottom"`, or `"distribute"`. \n'
245
246
  "The argument passed was {vertical_alignment}.",
246
247
  vertical_alignment=vertical_alignment,
248
+ element_type=element_type,
247
249
  )
248
250
 
249
251
 
250
252
  class StreamlitInvalidColumnGapError(LocalizableStreamlitException):
251
253
  """Exception raised when an invalid value is specified for gap."""
252
254
 
253
- def __init__(self, gap: str) -> None:
255
+ def __init__(self, gap: str, element_type: str) -> None:
254
256
  super().__init__(
255
- 'The `gap` argument to `st.columns` must be `"small"`, `"medium"`, `"large"`, or `"none"`. \n'
257
+ 'The `gap` argument to `{element_type}` must be `"small"`, `"medium"`, `"large"`, or `"none"`. \n'
256
258
  "The argument passed was {gap}.",
257
259
  gap=gap,
260
+ element_type=element_type,
261
+ )
262
+
263
+
264
+ class StreamlitInvalidHorizontalAlignmentError(LocalizableStreamlitException):
265
+ """Exception raised when an invalid value is specified for horizontal_alignment."""
266
+
267
+ def __init__(self, horizontal_alignment: str, element_type: str) -> None:
268
+ super().__init__(
269
+ "The `horizontal_alignment` argument to `{element_type}` must be "
270
+ '`"left"`, `"center"`, `"right"`, or `"distribute"`. \n'
271
+ "The argument passed was {horizontal_alignment}.",
272
+ horizontal_alignment=horizontal_alignment,
273
+ element_type=element_type,
258
274
  )
259
275
 
260
276
 
streamlit/file_util.py CHANGED
@@ -244,7 +244,7 @@ def normalize_path_join(*args: str) -> str:
244
244
  str
245
245
  The normalized path of the joined path.
246
246
  """
247
- return os.path.normpath(os.path.join(*args))
247
+ return os.path.normpath(os.path.join(*args)) # ty: ignore[no-matching-overload]
248
248
 
249
249
 
250
250
  def get_main_script_directory(main_script: str) -> str:
streamlit/git_util.py CHANGED
@@ -47,7 +47,7 @@ class GitRepo:
47
47
  self.repo = git.Repo(path, search_parent_directories=True)
48
48
  self.git_version = self.repo.git.version_info
49
49
 
50
- if self.git_version >= MIN_GIT_VERSION:
50
+ if self.git_version is not None and self.git_version >= MIN_GIT_VERSION:
51
51
  git_root = self.repo.git.rev_parse("--show-toplevel")
52
52
  self.module = os.path.relpath(path, git_root)
53
53
  except Exception:
streamlit/logger.py CHANGED
@@ -18,7 +18,7 @@ from __future__ import annotations
18
18
 
19
19
  import logging
20
20
  import sys
21
- from typing import Final
21
+ from typing import Final, cast
22
22
 
23
23
  DEFAULT_LOG_MESSAGE: Final = "%(asctime)s %(levelname) -7s %(name)s: %(message)s"
24
24
 
@@ -61,7 +61,7 @@ def setup_formatter(logger: logging.Logger) -> None:
61
61
  """Set up the console formatter for a given logger."""
62
62
  # Deregister any previous console loggers.
63
63
  if hasattr(logger, "streamlit_console_handler"):
64
- logger.removeHandler(logger.streamlit_console_handler)
64
+ logger.removeHandler(cast("logging.Handler", logger.streamlit_console_handler))
65
65
 
66
66
  logger.streamlit_console_handler = logging.StreamHandler() # type: ignore[attr-defined]
67
67