streamlit-nightly 1.45.1.dev20250508__py3-none-any.whl → 1.45.1.dev20250509__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 (188) hide show
  1. streamlit/auth_util.py +3 -3
  2. streamlit/cli_util.py +3 -2
  3. streamlit/commands/logo.py +2 -2
  4. streamlit/commands/navigation.py +5 -4
  5. streamlit/commands/page_config.py +3 -1
  6. streamlit/components/types/base_custom_component.py +7 -7
  7. streamlit/components/v1/custom_component.py +6 -6
  8. streamlit/config.py +9 -9
  9. streamlit/config_option.py +2 -2
  10. streamlit/connections/base_connection.py +3 -3
  11. streamlit/connections/snowflake_connection.py +5 -5
  12. streamlit/connections/snowpark_connection.py +3 -3
  13. streamlit/connections/sql_connection.py +9 -10
  14. streamlit/cursor.py +6 -6
  15. streamlit/delta_generator.py +7 -6
  16. streamlit/delta_generator_singletons.py +2 -2
  17. streamlit/deprecation_util.py +1 -1
  18. streamlit/elements/arrow.py +2 -3
  19. streamlit/elements/dialog_decorator.py +3 -3
  20. streamlit/elements/doc_string.py +20 -20
  21. streamlit/elements/layouts.py +26 -7
  22. streamlit/elements/lib/built_in_chart_utils.py +37 -39
  23. streamlit/elements/lib/color_util.py +3 -3
  24. streamlit/elements/lib/column_types.py +2 -2
  25. streamlit/elements/lib/dialog.py +2 -2
  26. streamlit/elements/lib/event_utils.py +1 -1
  27. streamlit/elements/lib/mutable_status_container.py +1 -1
  28. streamlit/elements/lib/policies.py +3 -3
  29. streamlit/elements/lib/utils.py +5 -5
  30. streamlit/elements/progress.py +9 -12
  31. streamlit/elements/vega_charts.py +2 -2
  32. streamlit/elements/widgets/button_group.py +2 -2
  33. streamlit/elements/widgets/data_editor.py +2 -2
  34. streamlit/elements/widgets/multiselect.py +2 -2
  35. streamlit/elements/widgets/selectbox.py +1 -1
  36. streamlit/elements/widgets/slider.py +16 -14
  37. streamlit/elements/write.py +3 -6
  38. streamlit/errors.py +34 -21
  39. streamlit/external/langchain/streamlit_callback_handler.py +2 -2
  40. streamlit/file_util.py +8 -8
  41. streamlit/git_util.py +1 -1
  42. streamlit/hello/dataframe_demo.py +1 -1
  43. streamlit/hello/mapping_demo.py +1 -1
  44. streamlit/navigation/page.py +1 -1
  45. streamlit/proto/Block_pb2.py +38 -29
  46. streamlit/proto/Block_pb2.pyi +68 -4
  47. streamlit/proto/GapSize_pb2.py +29 -0
  48. streamlit/proto/GapSize_pb2.pyi +70 -0
  49. streamlit/proto/HeightConfig_pb2.py +27 -0
  50. streamlit/proto/HeightConfig_pb2.pyi +48 -0
  51. streamlit/proto/WidthConfig_pb2.py +2 -2
  52. streamlit/proto/WidthConfig_pb2.pyi +15 -1
  53. streamlit/runtime/app_session.py +2 -2
  54. streamlit/runtime/caching/cache_data_api.py +9 -5
  55. streamlit/runtime/caching/cache_errors.py +3 -3
  56. streamlit/runtime/caching/cache_resource_api.py +7 -7
  57. streamlit/runtime/caching/cache_utils.py +9 -9
  58. streamlit/runtime/caching/cached_message_replay.py +1 -1
  59. streamlit/runtime/caching/hashing.py +70 -74
  60. streamlit/runtime/caching/legacy_cache_api.py +1 -1
  61. streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +3 -1
  62. streamlit/runtime/caching/storage/local_disk_cache_storage.py +1 -1
  63. streamlit/runtime/connection_factory.py +12 -12
  64. streamlit/runtime/context.py +2 -2
  65. streamlit/runtime/credentials.py +3 -3
  66. streamlit/runtime/fragment.py +3 -4
  67. streamlit/runtime/media_file_manager.py +2 -2
  68. streamlit/runtime/memory_media_file_storage.py +1 -1
  69. streamlit/runtime/memory_uploaded_file_manager.py +1 -1
  70. streamlit/runtime/metrics_util.py +5 -6
  71. streamlit/runtime/pages_manager.py +3 -3
  72. streamlit/runtime/runtime.py +1 -1
  73. streamlit/runtime/runtime_util.py +2 -2
  74. streamlit/runtime/scriptrunner/exec_code.py +10 -3
  75. streamlit/runtime/scriptrunner/magic.py +13 -8
  76. streamlit/runtime/scriptrunner/script_runner.py +2 -2
  77. streamlit/runtime/scriptrunner_utils/exceptions.py +1 -1
  78. streamlit/runtime/scriptrunner_utils/script_run_context.py +6 -5
  79. streamlit/runtime/secrets.py +8 -11
  80. streamlit/runtime/state/query_params.py +2 -2
  81. streamlit/runtime/state/safe_session_state.py +2 -2
  82. streamlit/runtime/state/session_state.py +17 -15
  83. streamlit/runtime/stats.py +1 -1
  84. streamlit/runtime/uploaded_file_manager.py +1 -1
  85. streamlit/source_util.py +3 -4
  86. streamlit/static/index.html +1 -1
  87. streamlit/static/static/js/{ErrorOutline.esm.C9UoaGEN.js → ErrorOutline.esm.C-0hf1-k.js} +1 -1
  88. streamlit/static/static/js/{FileDownload.esm.DoToR9q0.js → FileDownload.esm.B-fFGI-X.js} +1 -1
  89. streamlit/static/static/js/{FileHelper.Bt4VJ--Q.js → FileHelper.ACYo0OZo.js} +1 -1
  90. streamlit/static/static/js/{FormClearHelper.D5PbW8FI.js → FormClearHelper.CVNTT-bJ.js} +1 -1
  91. streamlit/static/static/js/{Hooks.DgkQ2Xp9.js → Hooks.C3thlpd2.js} +1 -1
  92. streamlit/static/static/js/{InputInstructions.DLnLhwHI.js → InputInstructions.CwAxousX.js} +1 -1
  93. streamlit/static/static/js/{ProgressBar.BtSgh_K-.js → ProgressBar.xh599Rum.js} +1 -1
  94. streamlit/static/static/js/{RenderInPortalIfExists.CjdyBvQX.js → RenderInPortalIfExists.CQLIsNPE.js} +1 -1
  95. streamlit/static/static/js/{Toolbar.CAYIzVZk.js → Toolbar.LKdyvP0u.js} +1 -1
  96. streamlit/static/static/js/{base-input.CD4xW4_9.js → base-input.D8OdS4WW.js} +1 -1
  97. streamlit/static/static/js/{checkbox.Ba4jj5dR.js → checkbox.DSdYKlOI.js} +1 -1
  98. streamlit/static/static/js/{createSuper.BBGT9Ijd.js → createSuper.B2pyCfWw.js} +1 -1
  99. streamlit/static/static/js/{data-grid-overlay-editor.CYuk1Aj7.js → data-grid-overlay-editor.DhO2r0ne.js} +1 -1
  100. streamlit/static/static/js/{downloader.DM9KEOCw.js → downloader.C24skoDM.js} +1 -1
  101. streamlit/static/static/js/{es6.FqM62T4b.js → es6.DHkvCKPh.js} +2 -2
  102. streamlit/static/static/js/{iframeResizer.contentWindow.s2B09mw2.js → iframeResizer.contentWindow.2ckQaC2c.js} +1 -1
  103. streamlit/static/static/js/index.0dGwl8CJ.js +1 -0
  104. streamlit/static/static/js/index.B5A28NpR.js +1 -0
  105. streamlit/static/static/js/{index.B9FiDQ3U.js → index.B5EFweZ4.js} +1 -1
  106. streamlit/static/static/js/{index.DkGCnTMe.js → index.BAafqHfB.js} +1 -1
  107. streamlit/static/static/js/{index.BMXmhMlZ.js → index.BHTbGZPQ.js} +1 -1
  108. streamlit/static/static/js/{index.CpDFZQ4Y.js → index.BNXtQAj4.js} +1 -1
  109. streamlit/static/static/js/index.BRhKaVdO.js +1 -0
  110. streamlit/static/static/js/index.BSOiJVQd.js +2 -0
  111. streamlit/static/static/js/{index.BoMRR3tN.js → index.BVgTQbOJ.js} +1 -1
  112. streamlit/static/static/js/{index.Cwtbhfaf.js → index.BflIniLm.js} +1 -1
  113. streamlit/static/static/js/{index.DMrO9G6A.js → index.BjeNtZIz.js} +1 -1
  114. streamlit/static/static/js/{index.C2qCX1Lh.js → index.By-NmdnB.js} +151 -151
  115. streamlit/static/static/js/{index.b9kK7Vzl.js → index.CIoOEhZ2.js} +1 -1
  116. streamlit/static/static/js/{index.CEKMSkSh.js → index.CRCdonis.js} +36 -36
  117. streamlit/static/static/js/{index.T5LKPcND.js → index.CRxaBCJ7.js} +1 -1
  118. streamlit/static/static/js/{index.CeiCniCg.js → index.CU-pbYVN.js} +1 -1
  119. streamlit/static/static/js/{index.BVA8TXNT.js → index.CUsk52t2.js} +1 -1
  120. streamlit/static/static/js/{index.CH9XN_-G.js → index.CVO14oQG.js} +2 -2
  121. streamlit/static/static/js/index.CXFuA6J-.js +1 -0
  122. streamlit/static/static/js/{index.DQi04JYE.js → index.C_dd5q7u.js} +1 -1
  123. streamlit/static/static/js/{index.DTi8Lw0k.js → index.CjWUnKIN.js} +1 -1
  124. streamlit/static/static/js/{index.DG8IxVeM.js → index.CkTL9bAR.js} +2 -2
  125. streamlit/static/static/js/{index.D9FvPPrI.js → index.CsbhsAPy.js} +1 -1
  126. streamlit/static/static/js/{index.R0peMEpV.js → index.CtCnBUtk.js} +1 -1
  127. streamlit/static/static/js/{index.CP2PmB93.js → index.CwuKadAX.js} +1 -1
  128. streamlit/static/static/js/{index.BFqpCk2P.js → index.D0R7Xh4Z.js} +1 -1
  129. streamlit/static/static/js/{index.DSDkXosb.js → index.D2D75EDw.js} +2 -2
  130. streamlit/static/static/js/{index.BsjuUMyW.js → index.D4eMiZ1F.js} +1 -1
  131. streamlit/static/static/js/{index.BDTYk2an.js → index.D7SCC3z9.js} +1 -1
  132. streamlit/static/static/js/{index.JTeVe9GQ.js → index.DZiilxEt.js} +1 -1
  133. streamlit/static/static/js/{index.BY7-qCf5.js → index.Dvr1cEJS.js} +1 -1
  134. streamlit/static/static/js/index.JtIlC6Uq.js +1 -0
  135. streamlit/static/static/js/index.fz_c3Xh_.js +1 -0
  136. streamlit/static/static/js/{index.CqaahZPf.js → index.gFjPlsMT.js} +1 -1
  137. streamlit/static/static/js/{index.0pkoyBcb.js → index.jCJYMVED.js} +1 -1
  138. streamlit/static/static/js/{index.DWaB7Scf.js → index.xldt56AE.js} +1 -1
  139. streamlit/static/static/js/{index.CyE1OdOj.js → index.yzoj_DuM.js} +1 -1
  140. streamlit/static/static/js/{input.DMOGBelK.js → input.BP6LX_Bg.js} +1 -1
  141. streamlit/static/static/js/{memory.DmCktBGW.js → memory.E9x2ZYJv.js} +1 -1
  142. streamlit/static/static/js/{mergeWith.DeWTsJ5h.js → mergeWith.CZP2AaVS.js} +1 -1
  143. streamlit/static/static/js/{number-overlay-editor.DDFelcUP.js → number-overlay-editor.D-Kl79U_.js} +1 -1
  144. streamlit/static/static/js/{possibleConstructorReturn.CYJtAqB-.js → possibleConstructorReturn.P2ILVC_6.js} +1 -1
  145. streamlit/static/static/js/{sandbox.CfaU9Ih9.js → sandbox.DfzJIGMV.js} +1 -1
  146. streamlit/static/static/js/{textarea.7hWYKDw2.js → textarea.4PjzfDWF.js} +1 -1
  147. streamlit/static/static/js/{timepicker.DZsgZ9oE.js → timepicker.DMQdaNzO.js} +1 -1
  148. streamlit/static/static/js/{toConsumableArray.CqWB4Jry.js → toConsumableArray.BEdkbHYx.js} +1 -1
  149. streamlit/static/static/js/{uniqueId.DQ533D9O.js → uniqueId.CAs7ftHC.js} +1 -1
  150. streamlit/static/static/js/{useBasicWidgetState.-99xbU_o.js → useBasicWidgetState.Cedp0V76.js} +1 -1
  151. streamlit/static/static/js/{useOnInputChange.B4G2Q7Bu.js → useOnInputChange.CvRKHHKx.js} +1 -1
  152. streamlit/static/static/js/{withFullScreenWrapper.BJQZ2aNc.js → withFullScreenWrapper.BbmjZAzW.js} +1 -1
  153. streamlit/string_util.py +6 -7
  154. streamlit/temporary_directory.py +12 -3
  155. streamlit/testing/v1/app_test.py +11 -6
  156. streamlit/testing/v1/element_tree.py +134 -158
  157. streamlit/testing/v1/local_script_runner.py +5 -5
  158. streamlit/testing/v1/util.py +11 -4
  159. streamlit/type_util.py +3 -4
  160. streamlit/user_info.py +3 -2
  161. streamlit/util.py +1 -1
  162. streamlit/watcher/event_based_path_watcher.py +1 -1
  163. streamlit/watcher/folder_black_list.py +1 -1
  164. streamlit/watcher/local_sources_watcher.py +5 -5
  165. streamlit/watcher/path_watcher.py +1 -1
  166. streamlit/web/cli.py +12 -11
  167. streamlit/web/server/browser_websocket_handler.py +1 -1
  168. streamlit/web/server/component_request_handler.py +1 -1
  169. streamlit/web/server/media_file_handler.py +2 -1
  170. streamlit/web/server/oauth_authlib_routes.py +2 -2
  171. streamlit/web/server/oidc_mixin.py +13 -6
  172. streamlit/web/server/routes.py +3 -3
  173. streamlit/web/server/server.py +1 -1
  174. streamlit/web/server/server_util.py +7 -6
  175. streamlit/web/server/upload_file_request_handler.py +5 -5
  176. {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/METADATA +1 -1
  177. {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/RECORD +181 -177
  178. {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/WHEEL +1 -1
  179. streamlit/static/static/js/index.CCD4LJ9Q.js +0 -1
  180. streamlit/static/static/js/index.CbLZDRQu.js +0 -1
  181. streamlit/static/static/js/index.D9qEk5xd.js +0 -1
  182. streamlit/static/static/js/index.DTXSsTgK.js +0 -1
  183. streamlit/static/static/js/index.DqVjOqxm.js +0 -1
  184. streamlit/static/static/js/index.RHbaxsqm.js +0 -1
  185. streamlit/static/static/js/index.hT9gkW3a.js +0 -2
  186. {streamlit_nightly-1.45.1.dev20250508.data → streamlit_nightly-1.45.1.dev20250509.data}/scripts/streamlit.cmd +0 -0
  187. {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/entry_points.txt +0 -0
  188. {streamlit_nightly-1.45.1.dev20250508.dist-info → streamlit_nightly-1.45.1.dev20250509.dist-info}/top_level.txt +0 -0
@@ -34,7 +34,7 @@ import weakref
34
34
  from enum import Enum
35
35
  from re import Pattern
36
36
  from types import MappingProxyType
37
- from typing import Any, Callable, Final, Union, cast
37
+ from typing import TYPE_CHECKING, Any, Callable, Final, Union, cast
38
38
 
39
39
  from typing_extensions import TypeAlias
40
40
 
@@ -44,6 +44,10 @@ from streamlit.runtime.caching.cache_errors import UnhashableTypeError
44
44
  from streamlit.runtime.caching.cache_type import CacheType
45
45
  from streamlit.runtime.uploaded_file_manager import UploadedFile
46
46
 
47
+ if TYPE_CHECKING:
48
+ import numpy.typing as npt
49
+ from PIL.Image import Image
50
+
47
51
  _LOGGER: Final = logger.get_logger(__name__)
48
52
 
49
53
  # If a dataframe has more than this many rows, we consider it large and hash a sample.
@@ -66,11 +70,11 @@ _CYCLE_PLACEHOLDER: Final = (
66
70
  class UserHashError(StreamlitAPIException):
67
71
  def __init__(
68
72
  self,
69
- orig_exc,
70
- object_to_hash,
71
- hash_func,
73
+ orig_exc: BaseException,
74
+ object_to_hash: Any,
75
+ hash_func: Callable[[Any], Any],
72
76
  cache_type: CacheType | None = None,
73
- ):
77
+ ) -> None:
74
78
  self.alternate_name = type(orig_exc).__name__
75
79
  self.hash_func = hash_func
76
80
  self.cache_type = cache_type
@@ -80,7 +84,11 @@ class UserHashError(StreamlitAPIException):
80
84
  super().__init__(msg)
81
85
  self.with_traceback(orig_exc.__traceback__)
82
86
 
83
- def _get_message_from_func(self, orig_exc, cached_func):
87
+ def _get_message_from_func(
88
+ self,
89
+ orig_exc: BaseException,
90
+ cached_func: Any,
91
+ ) -> str:
84
92
  args = self._get_error_message_args(orig_exc, cached_func)
85
93
 
86
94
  return (
@@ -145,7 +153,7 @@ If you think this is actually a Streamlit bug, please
145
153
 
146
154
  def update_hash(
147
155
  val: Any,
148
- hasher,
156
+ hasher: Any,
149
157
  cache_type: CacheType,
150
158
  hash_source: Callable[..., Any] | None = None,
151
159
  hash_funcs: HashFuncsDict | None = None,
@@ -182,13 +190,13 @@ class _HashStack:
182
190
  def __repr__(self) -> str:
183
191
  return util.repr_(self)
184
192
 
185
- def push(self, val: Any):
193
+ def push(self, val: Any) -> None:
186
194
  self._stack[id(val)] = val
187
195
 
188
- def pop(self):
196
+ def pop(self) -> None:
189
197
  self._stack.popitem()
190
198
 
191
- def __contains__(self, val: Any):
199
+ def __contains__(self, val: Any) -> bool:
192
200
  return id(val) in self._stack
193
201
 
194
202
  def pretty_print(self) -> str:
@@ -247,28 +255,20 @@ def _key(obj: Any | None) -> Any:
247
255
  if obj is None:
248
256
  return None
249
257
 
250
- def is_simple(obj):
258
+ def is_simple(obj: Any) -> bool:
251
259
  return (
252
- isinstance(obj, bytes)
253
- or isinstance(obj, bytearray)
254
- or isinstance(obj, str)
255
- or isinstance(obj, float)
256
- or isinstance(obj, int)
257
- or isinstance(obj, bool)
258
- or isinstance(obj, uuid.UUID)
260
+ isinstance(obj, (bytes, bytearray, str, float, int, bool, uuid.UUID))
259
261
  or obj is None
260
262
  )
261
263
 
262
264
  if is_simple(obj):
263
265
  return obj
264
266
 
265
- if isinstance(obj, tuple):
266
- if all(map(is_simple, obj)):
267
- return obj
267
+ if isinstance(obj, tuple) and all(map(is_simple, obj)):
268
+ return obj
268
269
 
269
- if isinstance(obj, list):
270
- if all(map(is_simple, obj)):
271
- return ("__l", tuple(obj))
270
+ if isinstance(obj, list) and all(map(is_simple, obj)):
271
+ return ("__l", tuple(obj))
272
272
 
273
273
  if inspect.isbuiltin(obj) or inspect.isroutine(obj) or inspect.iscode(obj):
274
274
  return id(obj)
@@ -279,7 +279,9 @@ def _key(obj: Any | None) -> Any:
279
279
  class _CacheFuncHasher:
280
280
  """A hasher that can hash objects with cycles."""
281
281
 
282
- def __init__(self, cache_type: CacheType, hash_funcs: HashFuncsDict | None = None):
282
+ def __init__(
283
+ self, cache_type: CacheType, hash_funcs: HashFuncsDict | None = None
284
+ ) -> None:
283
285
  # Can't use types as the keys in the internal _hash_funcs because
284
286
  # we always remove user-written modules from memory when rerunning a
285
287
  # script in order to reload it and grab the latest code changes.
@@ -339,7 +341,7 @@ class _CacheFuncHasher:
339
341
 
340
342
  return b
341
343
 
342
- def update(self, hasher, obj: Any) -> None:
344
+ def update(self, hasher: Any, obj: Any) -> None:
343
345
  """Update the provided hasher with the hash of an object."""
344
346
  b = self.to_bytes(obj)
345
347
  hasher.update(b)
@@ -360,10 +362,10 @@ class _CacheFuncHasher:
360
362
  # deep, so we don't try to hash them at all.
361
363
  return self.to_bytes(id(obj))
362
364
 
363
- elif isinstance(obj, bytes) or isinstance(obj, bytearray):
365
+ if isinstance(obj, bytes) or isinstance(obj, bytearray):
364
366
  return obj
365
367
 
366
- elif type_util.get_fqn_type(obj) in self._hash_funcs:
368
+ if type_util.get_fqn_type(obj) in self._hash_funcs:
367
369
  # Escape hatch for unsupported objects
368
370
  hash_func = self._hash_funcs[type_util.get_fqn_type(obj)]
369
371
  try:
@@ -374,57 +376,59 @@ class _CacheFuncHasher:
374
376
  ) from ex
375
377
  return self.to_bytes(output)
376
378
 
377
- elif isinstance(obj, str):
379
+ if isinstance(obj, str):
378
380
  return obj.encode()
379
381
 
380
- elif isinstance(obj, float):
382
+ if isinstance(obj, float):
381
383
  return _float_to_bytes(obj)
382
384
 
383
- elif isinstance(obj, int):
385
+ if isinstance(obj, int):
384
386
  return _int_to_bytes(obj)
385
387
 
386
- elif isinstance(obj, uuid.UUID):
388
+ if isinstance(obj, uuid.UUID):
387
389
  return obj.bytes
388
390
 
389
- elif isinstance(obj, datetime.datetime):
391
+ if isinstance(obj, datetime.datetime):
390
392
  return obj.isoformat().encode()
391
393
 
392
- elif isinstance(obj, (list, tuple)):
394
+ if isinstance(obj, (list, tuple)):
393
395
  for item in obj:
394
396
  self.update(h, item)
395
397
  return h.digest()
396
398
 
397
- elif isinstance(obj, dict):
399
+ if isinstance(obj, dict):
398
400
  for item in obj.items():
399
401
  self.update(h, item)
400
402
  return h.digest()
401
403
 
402
- elif obj is None:
404
+ if obj is None:
403
405
  return b"0"
404
406
 
405
- elif obj is True:
407
+ if obj is True:
406
408
  return b"1"
407
409
 
408
- elif obj is False:
410
+ if obj is False:
409
411
  return b"0"
410
412
 
411
- elif not isinstance(obj, type) and dataclasses.is_dataclass(obj):
413
+ if not isinstance(obj, type) and dataclasses.is_dataclass(obj):
412
414
  return self.to_bytes(dataclasses.asdict(obj))
413
- elif isinstance(obj, Enum):
415
+ if isinstance(obj, Enum):
414
416
  return str(obj).encode()
415
417
 
416
- elif type_util.is_type(obj, "pandas.core.series.Series"):
418
+ if type_util.is_type(obj, "pandas.core.series.Series"):
417
419
  import pandas as pd
418
420
 
419
- obj = cast("pd.Series", obj)
420
- self.update(h, obj.size)
421
- self.update(h, obj.dtype.name)
421
+ series_obj: pd.Series = cast("pd.Series", obj)
422
+ self.update(h, series_obj.size)
423
+ self.update(h, series_obj.dtype.name)
422
424
 
423
- if len(obj) >= _PANDAS_ROWS_LARGE:
424
- obj = obj.sample(n=_PANDAS_SAMPLE_SIZE, random_state=0)
425
+ if len(series_obj) >= _PANDAS_ROWS_LARGE:
426
+ series_obj = series_obj.sample(n=_PANDAS_SAMPLE_SIZE, random_state=0)
425
427
 
426
428
  try:
427
- self.update(h, pd.util.hash_pandas_object(obj).to_numpy().tobytes())
429
+ self.update(
430
+ h, pd.util.hash_pandas_object(series_obj).to_numpy().tobytes()
431
+ )
428
432
  return h.digest()
429
433
  except TypeError:
430
434
  _LOGGER.warning(
@@ -434,22 +438,22 @@ class _CacheFuncHasher:
434
438
 
435
439
  # Use pickle if pandas cannot hash the object for example if
436
440
  # it contains unhashable objects.
437
- return b"%s" % pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
441
+ return b"%s" % pickle.dumps(series_obj, pickle.HIGHEST_PROTOCOL)
438
442
 
439
443
  elif type_util.is_type(obj, "pandas.core.frame.DataFrame"):
440
444
  import pandas as pd
441
445
 
442
- obj = cast("pd.DataFrame", obj)
443
- self.update(h, obj.shape)
446
+ df_obj: pd.DataFrame = cast("pd.DataFrame", obj)
447
+ self.update(h, df_obj.shape)
444
448
 
445
- if len(obj) >= _PANDAS_ROWS_LARGE:
446
- obj = obj.sample(n=_PANDAS_SAMPLE_SIZE, random_state=0)
449
+ if len(df_obj) >= _PANDAS_ROWS_LARGE:
450
+ df_obj = df_obj.sample(n=_PANDAS_SAMPLE_SIZE, random_state=0)
447
451
  try:
448
452
  column_hash_bytes = self.to_bytes(
449
- pd.util.hash_pandas_object(obj.dtypes)
453
+ pd.util.hash_pandas_object(df_obj.dtypes)
450
454
  )
451
455
  self.update(h, column_hash_bytes)
452
- values_hash_bytes = self.to_bytes(pd.util.hash_pandas_object(obj))
456
+ values_hash_bytes = self.to_bytes(pd.util.hash_pandas_object(df_obj))
453
457
  self.update(h, values_hash_bytes)
454
458
  return h.digest()
455
459
  except TypeError:
@@ -460,7 +464,7 @@ class _CacheFuncHasher:
460
464
 
461
465
  # Use pickle if pandas cannot hash the object for example if
462
466
  # it contains unhashable objects.
463
- return b"%s" % pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
467
+ return b"%s" % pickle.dumps(df_obj, pickle.HIGHEST_PROTOCOL)
464
468
 
465
469
  elif type_util.is_type(obj, "polars.series.series.Series"):
466
470
  import polars as pl # type: ignore[import-not-found]
@@ -513,39 +517,32 @@ class _CacheFuncHasher:
513
517
  # it contains unhashable objects.
514
518
  return b"%s" % pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
515
519
  elif type_util.is_type(obj, "numpy.ndarray"):
516
- import numpy as np
517
-
518
- # write cast type as string to make it work with our Python 3.8 tests
519
- # - can be removed once we sunset support for Python 3.8
520
- obj = cast("np.ndarray[Any, Any]", obj)
521
- self.update(h, obj.shape)
522
- self.update(h, str(obj.dtype))
520
+ np_obj: npt.NDArray[Any] = cast("npt.NDArray[Any]", obj)
521
+ self.update(h, np_obj.shape)
522
+ self.update(h, str(np_obj.dtype))
523
523
 
524
- if obj.size >= _NP_SIZE_LARGE:
524
+ if np_obj.size >= _NP_SIZE_LARGE:
525
525
  import numpy as np
526
526
 
527
527
  state = np.random.RandomState(0)
528
- obj = state.choice(obj.flat, size=_NP_SAMPLE_SIZE)
528
+ np_obj = state.choice(np_obj.flat, size=_NP_SAMPLE_SIZE)
529
529
 
530
- self.update(h, obj.tobytes())
530
+ self.update(h, np_obj.tobytes())
531
531
  return h.digest()
532
532
  elif type_util.is_type(obj, "PIL.Image.Image"):
533
533
  import numpy as np
534
- from PIL.Image import Image # noqa: TC002
535
534
 
536
- obj = cast("Image", obj)
535
+ pil_obj: Image = cast("Image", obj)
537
536
 
538
537
  # we don't just hash the results of obj.tobytes() because we want to use
539
538
  # the sampling logic for numpy data
540
- np_array = np.frombuffer(obj.tobytes(), dtype="uint8")
539
+ np_array = np.frombuffer(pil_obj.tobytes(), dtype="uint8")
541
540
  return self.to_bytes(np_array)
542
541
 
543
542
  elif inspect.isbuiltin(obj):
544
543
  return bytes(obj.__name__.encode())
545
544
 
546
- elif isinstance(obj, MappingProxyType) or isinstance(
547
- obj, collections.abc.ItemsView
548
- ):
545
+ elif isinstance(obj, (MappingProxyType, collections.abc.ItemsView)):
549
546
  return self.to_bytes(dict(obj))
550
547
 
551
548
  elif type_util.is_type(obj, "builtins.getset_descriptor"):
@@ -561,9 +558,8 @@ class _CacheFuncHasher:
561
558
  return h.digest()
562
559
 
563
560
  elif hasattr(obj, "name") and (
564
- isinstance(obj, io.IOBase)
565
561
  # Handle temporary files used during testing
566
- or isinstance(obj, tempfile._TemporaryFileWrapper)
562
+ isinstance(obj, (io.IOBase, tempfile._TemporaryFileWrapper))
567
563
  ):
568
564
  # Hash files as name + last modification date + offset.
569
565
  # NB: we're using hasattr("name") to differentiate between
@@ -579,7 +575,7 @@ class _CacheFuncHasher:
579
575
  elif isinstance(obj, Pattern):
580
576
  return self.to_bytes([obj.pattern, obj.flags])
581
577
 
582
- elif isinstance(obj, io.StringIO) or isinstance(obj, io.BytesIO):
578
+ elif isinstance(obj, (io.StringIO, io.BytesIO)):
583
579
  # Hash in-memory StringIO/BytesIO by their full contents
584
580
  # and seek position.
585
581
  self.update(h, obj.tell())
@@ -40,7 +40,7 @@ def cache(
40
40
  hash_funcs: HashFuncsDict | None = None,
41
41
  max_entries: int | None = None,
42
42
  ttl: float | None = None,
43
- ):
43
+ ) -> F:
44
44
  """Legacy caching decorator (deprecated).
45
45
 
46
46
  Legacy caching with ``st.cache`` has been removed from Streamlit. This is
@@ -57,7 +57,9 @@ class InMemoryCacheStorageWrapper(CacheStorage):
57
57
  it from multiple threads.
58
58
  """
59
59
 
60
- def __init__(self, persist_storage: CacheStorage, context: CacheStorageContext):
60
+ def __init__(
61
+ self, persist_storage: CacheStorage, context: CacheStorageContext
62
+ ) -> None:
61
63
  self.function_key = context.function_key
62
64
  self.function_display_name = context.function_display_name
63
65
  self._ttl_seconds = context.ttl_seconds
@@ -120,7 +120,7 @@ class LocalDiskCacheStorage(CacheStorage):
120
120
  This is the default cache persistence layer for `@st.cache_data`.
121
121
  """
122
122
 
123
- def __init__(self, context: CacheStorageContext):
123
+ def __init__(self, context: CacheStorageContext) -> None:
124
124
  self.function_key = context.function_key
125
125
  self.persist = context.persist
126
126
  self._ttl_seconds = context.ttl_seconds
@@ -38,7 +38,7 @@ if TYPE_CHECKING:
38
38
  # 2. Writing two new @overloads for connection_factory (one for the case where the
39
39
  # only the connection name is specified and another when both name and type are).
40
40
  # 3. Updating test_get_first_party_connection_helper in connection_factory_test.py.
41
- FIRST_PARTY_CONNECTIONS = {
41
+ FIRST_PARTY_CONNECTIONS: Final[dict[str, type[BaseConnection[Any]]]] = {
42
42
  "snowflake": SnowflakeConnection,
43
43
  "snowpark": SnowparkConnection,
44
44
  "sql": SQLConnection,
@@ -65,7 +65,7 @@ def _create_connection(
65
65
  connection_class: type[ConnectionClass],
66
66
  max_entries: int | None = None,
67
67
  ttl: float | timedelta | None = None,
68
- **kwargs,
68
+ **kwargs: Any,
69
69
  ) -> ConnectionClass:
70
70
  """Create an instance of connection_class with the given name and kwargs.
71
71
 
@@ -76,7 +76,7 @@ def _create_connection(
76
76
  """
77
77
 
78
78
  def __create_connection(
79
- name: str, connection_class: type[ConnectionClass], **kwargs
79
+ name: str, connection_class: type[ConnectionClass], **kwargs: Any
80
80
  ) -> ConnectionClass:
81
81
  return connection_class(connection_name=name, **kwargs)
82
82
 
@@ -103,7 +103,7 @@ def _create_connection(
103
103
  return __create_connection(name, connection_class, **kwargs)
104
104
 
105
105
 
106
- def _get_first_party_connection(connection_class: str):
106
+ def _get_first_party_connection(connection_class: str) -> type[BaseConnection[Any]]:
107
107
  if connection_class in FIRST_PARTY_CONNECTIONS:
108
108
  return FIRST_PARTY_CONNECTIONS[connection_class]
109
109
 
@@ -119,7 +119,7 @@ def connection_factory(
119
119
  max_entries: int | None = None,
120
120
  ttl: float | timedelta | None = None,
121
121
  autocommit: bool = False,
122
- **kwargs,
122
+ **kwargs: Any,
123
123
  ) -> SQLConnection:
124
124
  pass
125
125
 
@@ -131,7 +131,7 @@ def connection_factory(
131
131
  max_entries: int | None = None,
132
132
  ttl: float | timedelta | None = None,
133
133
  autocommit: bool = False,
134
- **kwargs,
134
+ **kwargs: Any,
135
135
  ) -> SQLConnection:
136
136
  pass
137
137
 
@@ -142,7 +142,7 @@ def connection_factory(
142
142
  max_entries: int | None = None,
143
143
  ttl: float | timedelta | None = None,
144
144
  autocommit: bool = False,
145
- **kwargs,
145
+ **kwargs: Any,
146
146
  ) -> SnowflakeConnection:
147
147
  pass
148
148
 
@@ -154,7 +154,7 @@ def connection_factory(
154
154
  max_entries: int | None = None,
155
155
  ttl: float | timedelta | None = None,
156
156
  autocommit: bool = False,
157
- **kwargs,
157
+ **kwargs: Any,
158
158
  ) -> SnowflakeConnection:
159
159
  pass
160
160
 
@@ -164,7 +164,7 @@ def connection_factory(
164
164
  name: Literal["snowpark"],
165
165
  max_entries: int | None = None,
166
166
  ttl: float | timedelta | None = None,
167
- **kwargs,
167
+ **kwargs: Any,
168
168
  ) -> SnowparkConnection:
169
169
  pass
170
170
 
@@ -175,7 +175,7 @@ def connection_factory(
175
175
  type: Literal["snowpark"],
176
176
  max_entries: int | None = None,
177
177
  ttl: float | timedelta | None = None,
178
- **kwargs,
178
+ **kwargs: Any,
179
179
  ) -> SnowparkConnection:
180
180
  pass
181
181
 
@@ -186,7 +186,7 @@ def connection_factory(
186
186
  type: type[ConnectionClass],
187
187
  max_entries: int | None = None,
188
188
  ttl: float | timedelta | None = None,
189
- **kwargs,
189
+ **kwargs: Any,
190
190
  ) -> ConnectionClass:
191
191
  pass
192
192
 
@@ -197,7 +197,7 @@ def connection_factory(
197
197
  type: str | None = None,
198
198
  max_entries: int | None = None,
199
199
  ttl: float | timedelta | None = None,
200
- **kwargs,
200
+ **kwargs: Any,
201
201
  ) -> BaseConnection[Any]:
202
202
  pass
203
203
 
@@ -64,7 +64,7 @@ def _normalize_header(name: str) -> str:
64
64
 
65
65
 
66
66
  class StreamlitHeaders(Mapping[str, str]):
67
- def __init__(self, headers: Iterable[tuple[str, str]]):
67
+ def __init__(self, headers: Iterable[tuple[str, str]]) -> None:
68
68
  dict_like_headers: dict[str, list[str]] = {}
69
69
 
70
70
  for key, value in headers:
@@ -98,7 +98,7 @@ class StreamlitHeaders(Mapping[str, str]):
98
98
 
99
99
 
100
100
  class StreamlitCookies(Mapping[str, str]):
101
- def __init__(self, cookies: Mapping[str, str]):
101
+ def __init__(self, cookies: Mapping[str, str]) -> None:
102
102
  self._cookies = MappingProxyType(cookies)
103
103
 
104
104
  @classmethod
@@ -20,7 +20,7 @@ import json
20
20
  import os
21
21
  import sys
22
22
  import textwrap
23
- from typing import Final, NamedTuple, NoReturn
23
+ from typing import Final, NamedTuple, NoReturn, cast
24
24
  from uuid import uuid4
25
25
 
26
26
  from streamlit import cli_util, env_util, file_util, util
@@ -116,12 +116,12 @@ class Credentials:
116
116
  _singleton: Credentials | None = None
117
117
 
118
118
  @classmethod
119
- def get_current(cls):
119
+ def get_current(cls) -> Credentials:
120
120
  """Return the singleton instance."""
121
121
  if cls._singleton is None:
122
122
  Credentials()
123
123
 
124
- return Credentials._singleton
124
+ return cast("Credentials", Credentials._singleton)
125
125
 
126
126
  def __init__(self):
127
127
  """Initialize class."""
@@ -155,11 +155,10 @@ def _fragment(
155
155
  )
156
156
 
157
157
  return wrapper
158
- else:
159
- non_optional_func = func
158
+ non_optional_func = func
160
159
 
161
160
  @wraps(non_optional_func)
162
- def wrap(*args, **kwargs):
161
+ def wrap(*args: Any, **kwargs: Any) -> Any:
163
162
  from streamlit.delta_generator_singletons import context_dg_stack
164
163
 
165
164
  ctx = get_script_run_ctx()
@@ -176,7 +175,7 @@ def _fragment(
176
175
  # that the fragment is associated with the correct script running.
177
176
  initialized_active_script_hash = ctx.active_script_hash
178
177
 
179
- def wrapped_fragment():
178
+ def wrapped_fragment() -> Any:
180
179
  import streamlit as st
181
180
 
182
181
  if should_show_deprecation_warning:
@@ -45,7 +45,7 @@ def _get_session_id() -> str:
45
45
  class MediaFileMetadata:
46
46
  """Metadata that the MediaFileManager needs for each file it manages."""
47
47
 
48
- def __init__(self, kind: MediaFileKind = MediaFileKind.MEDIA):
48
+ def __init__(self, kind: MediaFileKind = MediaFileKind.MEDIA) -> None:
49
49
  self._kind = kind
50
50
  self._is_marked_for_delete = False
51
51
 
@@ -80,7 +80,7 @@ class MediaFileManager:
80
80
  we should address it at some point.)
81
81
  """
82
82
 
83
- def __init__(self, storage: MediaFileStorage):
83
+ def __init__(self, storage: MediaFileStorage) -> None:
84
84
  self._storage = storage
85
85
 
86
86
  # Dict of [file_id -> MediaFileMetadata]
@@ -89,7 +89,7 @@ class MemoryFile(NamedTuple):
89
89
 
90
90
 
91
91
  class MemoryMediaFileStorage(MediaFileStorage, CacheStatsProvider):
92
- def __init__(self, media_endpoint: str):
92
+ def __init__(self, media_endpoint: str) -> None:
93
93
  """Create a new MemoryMediaFileStorage instance.
94
94
 
95
95
  Parameters
@@ -35,7 +35,7 @@ class MemoryUploadedFileManager(UploadedFileManager):
35
35
  This class can be used safely from multiple threads simultaneously.
36
36
  """
37
37
 
38
- def __init__(self, upload_endpoint: str):
38
+ def __init__(self, upload_endpoint: str) -> None:
39
39
  self.file_storage: dict[str, dict[str, UploadedFileRec]] = defaultdict(dict)
40
40
  self.endpoint = upload_endpoint
41
41
 
@@ -239,7 +239,7 @@ class Installation:
239
239
  return util.repr_(self)
240
240
 
241
241
  @property
242
- def installation_id(self):
242
+ def installation_id(self) -> str:
243
243
  return self.installation_id_v3
244
244
 
245
245
 
@@ -284,7 +284,7 @@ def _get_arg_metadata(arg: object) -> str | None:
284
284
 
285
285
 
286
286
  def _get_command_telemetry(
287
- _command_func: Callable[..., Any], _command_name: str, *args, **kwargs
287
+ _command_func: Callable[..., Any], _command_name: str, *args: Any, **kwargs: Any
288
288
  ) -> Command:
289
289
  """Get telemetry information for the given callable and its arguments."""
290
290
  arg_keywords = inspect.getfullargspec(_command_func).args
@@ -391,12 +391,11 @@ def gather_metrics(name: str, func: F | None = None) -> Callable[[F], F] | F:
391
391
  )
392
392
 
393
393
  return wrapper
394
- else:
395
- # To make mypy type narrow F | None -> F
396
- non_optional_func = func
394
+ # To make mypy type narrow F | None -> F
395
+ non_optional_func = func
397
396
 
398
397
  @wraps(non_optional_func)
399
- def wrapped_func(*args, **kwargs):
398
+ def wrapped_func(*args: Any, **kwargs: Any) -> Any:
400
399
  from timeit import default_timer as timer
401
400
 
402
401
  exec_start = timer()
@@ -38,8 +38,8 @@ class PagesManager:
38
38
  self,
39
39
  main_script_path: ScriptPath,
40
40
  script_cache: ScriptCache | None = None,
41
- **kwargs,
42
- ):
41
+ **kwargs: Any,
42
+ ) -> None:
43
43
  self._main_script_path = main_script_path
44
44
  self._main_script_hash: PageHash = calc_md5(main_script_path)
45
45
  self._script_cache = script_cache
@@ -135,7 +135,7 @@ class PagesManager:
135
135
  self.intended_page_script_hash,
136
136
  self._pages.get(fallback_page_hash, None),
137
137
  )
138
- elif self.intended_page_name:
138
+ if self.intended_page_name:
139
139
  # If a user navigates directly to a non-main page of an app, the
140
140
  # the page name can identify the page script to run
141
141
  return next(
@@ -167,7 +167,7 @@ class Runtime:
167
167
  """
168
168
  return cls._instance is not None
169
169
 
170
- def __init__(self, config: RuntimeConfig):
170
+ def __init__(self, config: RuntimeConfig) -> None:
171
171
  """Create a Runtime instance. It won't be started yet.
172
172
 
173
173
  Runtime is *not* thread-safe. Its public methods are generally
@@ -31,7 +31,7 @@ _LOGGER: Final = getLogger(__name__)
31
31
  class MessageSizeError(MarkdownFormattedException):
32
32
  """Exception raised when a websocket message is larger than the configured limit."""
33
33
 
34
- def __init__(self, failed_msg_str: Any):
34
+ def __init__(self, failed_msg_str: Any) -> None:
35
35
  msg = self._get_message(failed_msg_str)
36
36
  super().__init__(msg)
37
37
 
@@ -55,7 +55,7 @@ of the client's browser and the Streamlit server._
55
55
  class BadDurationStringError(StreamlitAPIException):
56
56
  """Raised when a bad duration argument string is passed."""
57
57
 
58
- def __init__(self, duration: str):
58
+ def __init__(self, duration: str) -> None:
59
59
  MarkdownFormattedException.__init__(
60
60
  self,
61
61
  "TTL string doesn't look right. It should be formatted as"